diff --git a/build/Three.js b/build/Three.js index c99a5475dfc04e8b308d714388396eecd10c616b..f11f627c82e72581d50d29398e3c6f2900e092fb 100755 --- a/build/Three.js +++ b/build/Three.js @@ -1,23872 +1,576 @@ // Three.js r41/ROME - http://github.com/mrdoob/three.js -/** - * @author mr.doob / http://mrdoob.com/ - */ - -var THREE = THREE || {}; - -if ( ! window.Int32Array ) { - - window.Int32Array = Array; - window.Float32Array = Array; - -} -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.Color = function ( hex ) { - - this.setHex( hex ); - -}; - -THREE.Color.prototype = { - - copy : function ( color ) { - - this.r = color.r; - this.g = color.g; - this.b = color.b; - this.hex = color.hex; - - }, - - setHex : function ( hex ) { - - this.hex = ( ~~ hex ) & 0xffffff; - this.updateRGB(); - - }, - - setRGB : function ( r, g, b ) { - - this.r = r; - this.g = g; - this.b = b; - - this.updateHex(); - - }, - - setHSV : function ( h, s, v ) { - - // based on MochiKit implementation by Bob Ippolito - // h,s,v ranges are < 0.0 - 1.0 > - - var r, g, b, i, f, p, q, t; - - if ( v == 0.0 ) { - - r = g = b = 0; - - } else { - - i = Math.floor( h * 6 ); - f = ( h * 6 ) - i; - p = v * ( 1 - s ); - q = v * ( 1 - ( s * f ) ); - t = v * ( 1 - ( s * ( 1 - f ) ) ); - - switch ( i ) { - - case 1: r = q; g = v; b = p; break; - case 2: r = p; g = v; b = t; break; - case 3: r = p; g = q; b = v; break; - case 4: r = t; g = p; b = v; break; - case 5: r = v; g = p; b = q; break; - case 6: // fall through - case 0: r = v; g = t; b = p; break; - - } - - } - - this.setRGB( r, g, b ); - - }, - - updateHex : function () { - - this.hex = ~~ ( this.r * 255 ) << 16 ^ ~~ ( this.g * 255 ) << 8 ^ ~~ ( this.b * 255 ); - - }, - - updateRGB : function () { - - this.r = ( this.hex >> 16 & 255 ) / 255; - this.g = ( this.hex >> 8 & 255 ) / 255; - this.b = ( this.hex & 255 ) / 255; - - }, - - clone : function () { - - return new THREE.Color( this.hex ); - - } - -}; -/** - * @author mr.doob / http://mrdoob.com/ - * @author philogb / http://blog.thejit.org/ - * @author egraether / http://egraether.com/ - * @author zz85 / http://www.lab4games.net/zz85/blog - */ - -THREE.Vector2 = function ( x, y ) { - - this.set( - - x || 0, - y || 0 - - ); - -}; - -THREE.Vector2.prototype = { - - set : function ( x, y ) { - - this.x = x; - this.y = y; - - return this; - - }, - - copy : function ( v ) { - - this.x = v.x; - this.y = v.y; - - return this; - - }, - - clone : function () { - - return new THREE.Vector2( this.x, this.y ); - - }, - - - add : function ( v1, v2 ) { - - this.x = v1.x + v2.x; - this.y = v1.y + v2.y; - - return this; - - }, - - addSelf : function ( v ) { - - this.x += v.x; - this.y += v.y; - - return this; - - }, - - sub : function ( v1, v2 ) { - - this.x = v1.x - v2.x; - this.y = v1.y - v2.y; - - return this; - - }, - - subSelf : function ( v ) { - - this.x -= v.x; - this.y -= v.y; - - return this; - - }, - - multiplyScalar : function ( s ) { - - this.x *= s; - this.y *= s; - - return this; - - }, - - divideScalar : function ( s ) { - - if ( s ) { - - this.x /= s; - this.y /= s; - - } else { - - this.set( 0, 0 ); - - } - - return this; - - }, - - - negate : function() { - - return this.multiplyScalar( -1 ); - - }, - - dot : function ( v ) { - - return this.x * v.x + this.y * v.y; - - }, - - lengthSq : function () { - - return this.x * this.x + this.y * this.y; - - }, - - length : function () { - - return Math.sqrt( this.lengthSq() ); - - }, - - normalize : function () { - - return this.divideScalar( this.length() ); - - }, - - distanceTo : function ( v ) { - - return Math.sqrt( this.distanceToSquared( v ) ); - - }, - - distanceToSquared : function ( v ) { - - var dx = this.x - v.x, dy = this.y - v.y; - return dx * dx + dy * dy; - - }, - - - setLength : function ( l ) { - - return this.normalize().multiplyScalar( l ); - - }, - - // deprecated: same as normalize - - unit : function () { - - return this.normalize(); - - }, - - // danger, works only on numbers which are exactly the same - // (which may be not what is expected thanks to floating point precision) - // (should be probably using some tiny epsilon instead of equality) - - equals : function( v ) { - - return ( ( v.x == this.x ) && ( v.y == this.y ) ); - - } - -}; -/** - * @author mr.doob / http://mrdoob.com/ - * @author kile / http://kile.stravaganza.org/ - * @author philogb / http://blog.thejit.org/ - * @author mikael emtinger / http://gomo.se/ - * @author egraether / http://egraether.com/ - */ - -THREE.Vector3 = function ( x, y, z ) { - - this.set( - - x || 0, - y || 0, - z || 0 - - ); - -}; - - -THREE.Vector3.prototype = { - - set : function ( x, y, z ) { - - this.x = x; - this.y = y; - this.z = z; - - return this; - - }, - - copy : function ( v ) { - - this.x = v.x; - this.y = v.y; - this.z = v.z; - - return this; - - }, - - clone : function () { - - return new THREE.Vector3( this.x, this.y, this.z ); - - }, - - - add : function ( v1, v2 ) { - - this.x = v1.x + v2.x; - this.y = v1.y + v2.y; - this.z = v1.z + v2.z; - - return this; - - }, - - addSelf : function ( v ) { - - this.x += v.x; - this.y += v.y; - this.z += v.z; - - return this; - - }, - - addScalar : function ( s ) { - - this.x += s; - this.y += s; - this.z += s; - - return this; - - }, - - sub : function ( v1, v2 ) { - - this.x = v1.x - v2.x; - this.y = v1.y - v2.y; - this.z = v1.z - v2.z; - - return this; - - }, - - subSelf : function ( v ) { - - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - - return this; - - }, - - multiply : function ( a, b ) { - - this.x = a.x * b.x; - this.y = a.y * b.y; - this.z = a.z * b.z; - - return this; - - }, - - multiplySelf : function ( v ) { - - this.x *= v.x; - this.y *= v.y; - this.z *= v.y; - - return this; - - }, - - multiplyScalar : function ( s ) { - - this.x *= s; - this.y *= s; - this.z *= s; - - return this; - - }, - - divideSelf : function ( v ) { - - return this.divide( this, v ); - - }, - - divideScalar : function ( s ) { - - if ( s ) { - - this.x /= s; - this.y /= s; - this.z /= s; - - } else { - - this.set( 0, 0, 0 ); - - } - - return this; - - }, - - - negate : function() { - - return this.multiplyScalar( -1 ); - - }, - - dot : function ( v ) { - - return this.x * v.x + this.y * v.y + this.z * v.z; - - }, - - lengthSq : function () { - - return this.x * this.x + this.y * this.y + this.z * this.z; - - }, - - length : function () { - - return Math.sqrt( this.lengthSq() ); - - }, - - lengthManhattan : function () { - - // correct version - // return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); - - return this.x + this.y + this.z; - - }, - - normalize : function () { - - return this.divideScalar( this.length() ); - - }, - - setLength : function ( l ) { - - return this.normalize().multiplyScalar( l ); - - }, - - - cross : function ( a, b ) { - - this.x = a.y * b.z - a.z * b.y; - this.y = a.z * b.x - a.x * b.z; - this.z = a.x * b.y - a.y * b.x; - - return this; - - }, - - crossSelf : function ( v ) { - - return this.set( - - this.y * v.z - this.z * v.y, - this.z * v.x - this.x * v.z, - this.x * v.y - this.y * v.x - - ); - - }, - - - distanceTo : function ( v ) { - - return Math.sqrt( this.distanceToSquared( v ) ); - - }, - - distanceToSquared : function ( v ) { - - return new THREE.Vector3().sub( this, v ).lengthSq(); - - }, - - - setPositionFromMatrix : function ( m ) { - - this.x = m.n14; - this.y = m.n24; - this.z = m.n34; - - }, - - setRotationFromMatrix : function ( m ) { - - var cosY = Math.cos( this.y ); - - this.y = Math.asin( m.n13 ); - - if ( Math.abs( cosY ) > 0.00001 ) { - - this.x = Math.atan2( - m.n23 / cosY, m.n33 / cosY ); - this.z = Math.atan2( - m.n12 / cosY, m.n11 / cosY ); - - } else { - - this.x = 0; - this.z = Math.atan2( m.n21, m.n22 ); - - } - - }, - - isZero : function () { - - return ( this.lengthSq() < 0.0001 /* almostZero */ ); - - } - -}; -/** - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author philogb / http://blog.thejit.org/ - * @author mikael emtinger / http://gomo.se/ - * @author egraether / http://egraether.com/ - */ - -THREE.Vector4 = function ( x, y, z, w ) { - - this.set( - - x || 0, - y || 0, - z || 0, - w || 1 - - ); - -}; - -THREE.Vector4.prototype = { - - set : function ( x, y, z, w ) { - - this.x = x; - this.y = y; - this.z = z; - this.w = w; - - return this; - - }, - - copy : function ( v ) { - - return this.set( - - v.x, - v.y, - v.z, - v.w || 1.0 - - ); - - }, - - clone : function () { - - return new THREE.Vector4( this.x, this.y, this.z, this.w ); - - }, - - - add : function ( v1, v2 ) { - - this.x = v1.x + v2.x; - this.y = v1.y + v2.y; - this.z = v1.z + v2.z; - this.w = v1.w + v2.w; - - return this; - - }, - - addSelf : function ( v ) { - - this.x += v.x; - this.y += v.y; - this.z += v.z; - this.w += v.w; - - return this; - - }, - - sub : function ( v1, v2 ) { - - this.x = v1.x - v2.x; - this.y = v1.y - v2.y; - this.z = v1.z - v2.z; - this.w = v1.w - v2.w; - - return this; - - }, - - subSelf : function ( v ) { - - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - this.w -= v.w; - - return this; - - }, - - multiplyScalar : function ( s ) { - - this.x *= s; - this.y *= s; - this.z *= s; - this.w *= s; - - return this; - - }, - - divideScalar : function ( s ) { - - if ( s ) { - - this.x /= s; - this.y /= s; - this.z /= s; - this.w /= s; - - } else { - - this.set( 0, 0, 0, 1 ); - - } - - return this; - - }, - - - negate : function() { - - return this.multiplyScalar( -1 ); - - }, - - dot : function ( v ) { - - return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; - - }, - - lengthSq : function () { - - return this.dot( this ); - - }, - - length : function () { - - return Math.sqrt( this.lengthSq() ); - - }, - - normalize : function () { - - return this.divideScalar( this.length() ); - - }, - - setLength : function ( l ) { - - return this.normalize().multiplyScalar( l ); - - }, - - - lerpSelf : function ( v, alpha ) { - - this.x += (v.x - this.x) * alpha; - this.y += (v.y - this.y) * alpha; - this.z += (v.z - this.z) * alpha; - this.w += (v.w - this.w) * alpha; - - return this; - - }, - -}; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.Ray = function ( origin, direction ) { - - this.origin = origin || new THREE.Vector3(); - this.direction = direction || new THREE.Vector3(); - -} - -THREE.Ray.prototype = { - - intersectScene: function ( scene ) { - - return this.intersectObjects( scene.objects ); - - }, - - intersectObjects: function ( objects ) { - - var i, l, object, - intersects = []; - - for ( i = 0, l = objects.length; i < l; i ++ ) { - - intersects = intersects.concat( this.intersectObject( objects[ i ] ) ); - - } - - intersects.sort( function ( a, b ) { return a.distance - b.distance; } ); - - return intersects; - - }, - - intersectObject: function ( object ) { - - if ( object instanceof THREE.Particle ) { - - var distance = distanceFromIntersection( this.origin, this.direction, object ); - - if ( ! distance || distance > object.scale.x ) { - - return []; - - } - - return [ { - - distance: distance, - point: object.position, - face: null, - object: object - - } ]; - - } else if ( object instanceof THREE.Mesh ) { - - // Checking boundingSphere - - var distance = distanceFromIntersection( this.origin, this.direction, object ); - - if ( ! distance || distance > object.geometry.boundingSphere.radius * Math.max( object.scale.x, Math.max( object.scale.y, object.scale.z ) ) ) { - - return []; - - } - - // Checking faces - - var f, fl, face, a, b, c, d, normal, - dot, scalar, - origin, direction, - geometry = object.geometry, - vertices = geometry.vertices, - objMatrix, - intersect, intersects = [], - intersectPoint; - - for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) { - - face = geometry.faces[ f ]; - - origin = this.origin.clone(); - direction = this.direction.clone(); - - objMatrix = object.matrixWorld; - - a = objMatrix.multiplyVector3( vertices[ face.a ].position.clone() ); - b = objMatrix.multiplyVector3( vertices[ face.b ].position.clone() ); - c = objMatrix.multiplyVector3( vertices[ face.c ].position.clone() ); - d = face instanceof THREE.Face4 ? objMatrix.multiplyVector3( vertices[ face.d ].position.clone() ) : null; - - normal = object.matrixRotationWorld.multiplyVector3( face.normal.clone() ); - dot = direction.dot( normal ); - - if ( object.doubleSided || ( object.flipSided ? dot > 0 : dot < 0 ) ) { // Math.abs( dot ) > 0.0001 - - scalar = normal.dot( new THREE.Vector3().sub( a, origin ) ) / dot; - intersectPoint = origin.addSelf( direction.multiplyScalar( scalar ) ); - - if ( face instanceof THREE.Face3 ) { - - if ( pointInFace3( intersectPoint, a, b, c ) ) { - - intersect = { - - distance: this.origin.distanceTo( intersectPoint ), - point: intersectPoint, - face: face, - object: object - - }; - - intersects.push( intersect ); - - } - - } else if ( face instanceof THREE.Face4 ) { - - if ( pointInFace3( intersectPoint, a, b, d ) || pointInFace3( intersectPoint, b, c, d ) ) { - - intersect = { - - distance: this.origin.distanceTo( intersectPoint ), - point: intersectPoint, - face: face, - object: object - - }; - - intersects.push( intersect ); - - } - - } - - } - - } - - return intersects; - - } else { - - return []; - - } - - function distanceFromIntersection( origin, direction, object ) { - - var vector, dot, intersect, distance, - position = object.matrixWorld.getPosition(); - - vector = position.clone().subSelf( origin ); - dot = vector.dot( direction ); - - intersect = origin.clone().addSelf( direction.clone().multiplyScalar( dot ) ); - distance = position.distanceTo( intersect ); - - // TODO: Check if distance is negative (object behind camera). - - return distance; - - } - - // http://www.blackpawn.com/texts/pointinpoly/default.html - - function pointInFace3( p, a, b, c ) { - - var v0 = c.clone().subSelf( a ), v1 = b.clone().subSelf( a ), v2 = p.clone().subSelf( a ), - dot00 = v0.dot( v0 ), dot01 = v0.dot( v1 ), dot02 = v0.dot( v2 ), dot11 = v1.dot( v1 ), dot12 = v1.dot( v2 ), - - invDenom = 1 / ( dot00 * dot11 - dot01 * dot01 ), - u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom, - v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; - - return ( u > 0 ) && ( v > 0 ) && ( u + v < 1 ); - - } - - } - -}; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.Rectangle = function () { - - var _left, _top, _right, _bottom, - _width, _height, _isEmpty = true; - - function resize() { - - _width = _right - _left; - _height = _bottom - _top; - - } - - this.getX = function () { - - return _left; - - }; - - this.getY = function () { - - return _top; - - }; - - this.getWidth = function () { - - return _width; - - }; - - this.getHeight = function () { - - return _height; - - }; - - this.getLeft = function() { - - return _left; - - }; - - this.getTop = function() { - - return _top; - - }; - - this.getRight = function() { - - return _right; - - }; - - this.getBottom = function() { - - return _bottom; - - }; - - this.set = function ( left, top, right, bottom ) { - - _isEmpty = false; - - _left = left; _top = top; - _right = right; _bottom = bottom; - - resize(); - - }; - - this.addPoint = function ( x, y ) { - - if ( _isEmpty ) { - - _isEmpty = false; - _left = x; _top = y; - _right = x; _bottom = y; - - resize(); - - } else { - - _left = _left < x ? _left : x; // Math.min( _left, x ); - _top = _top < y ? _top : y; // Math.min( _top, y ); - _right = _right > x ? _right : x; // Math.max( _right, x ); - _bottom = _bottom > y ? _bottom : y; // Math.max( _bottom, y ); - - resize(); - } - - }; - - this.add3Points = function ( x1, y1, x2, y2, x3, y3 ) { - - if (_isEmpty) { - - _isEmpty = false; - _left = x1 < x2 ? ( x1 < x3 ? x1 : x3 ) : ( x2 < x3 ? x2 : x3 ); - _top = y1 < y2 ? ( y1 < y3 ? y1 : y3 ) : ( y2 < y3 ? y2 : y3 ); - _right = x1 > x2 ? ( x1 > x3 ? x1 : x3 ) : ( x2 > x3 ? x2 : x3 ); - _bottom = y1 > y2 ? ( y1 > y3 ? y1 : y3 ) : ( y2 > y3 ? y2 : y3 ); - - resize(); - - } else { - - _left = x1 < x2 ? ( x1 < x3 ? ( x1 < _left ? x1 : _left ) : ( x3 < _left ? x3 : _left ) ) : ( x2 < x3 ? ( x2 < _left ? x2 : _left ) : ( x3 < _left ? x3 : _left ) ); - _top = y1 < y2 ? ( y1 < y3 ? ( y1 < _top ? y1 : _top ) : ( y3 < _top ? y3 : _top ) ) : ( y2 < y3 ? ( y2 < _top ? y2 : _top ) : ( y3 < _top ? y3 : _top ) ); - _right = x1 > x2 ? ( x1 > x3 ? ( x1 > _right ? x1 : _right ) : ( x3 > _right ? x3 : _right ) ) : ( x2 > x3 ? ( x2 > _right ? x2 : _right ) : ( x3 > _right ? x3 : _right ) ); - _bottom = y1 > y2 ? ( y1 > y3 ? ( y1 > _bottom ? y1 : _bottom ) : ( y3 > _bottom ? y3 : _bottom ) ) : ( y2 > y3 ? ( y2 > _bottom ? y2 : _bottom ) : ( y3 > _bottom ? y3 : _bottom ) ); - - resize(); - - }; - - }; - - this.addRectangle = function ( r ) { - - if ( _isEmpty ) { - - _isEmpty = false; - _left = r.getLeft(); _top = r.getTop(); - _right = r.getRight(); _bottom = r.getBottom(); - - resize(); - - } else { - - _left = _left < r.getLeft() ? _left : r.getLeft(); // Math.min(_left, r.getLeft() ); - _top = _top < r.getTop() ? _top : r.getTop(); // Math.min(_top, r.getTop() ); - _right = _right > r.getRight() ? _right : r.getRight(); // Math.max(_right, r.getRight() ); - _bottom = _bottom > r.getBottom() ? _bottom : r.getBottom(); // Math.max(_bottom, r.getBottom() ); - - resize(); - - } - - }; - - this.inflate = function ( v ) { - - _left -= v; _top -= v; - _right += v; _bottom += v; - - resize(); - - }; - - this.minSelf = function ( r ) { - - _left = _left > r.getLeft() ? _left : r.getLeft(); // Math.max( _left, r.getLeft() ); - _top = _top > r.getTop() ? _top : r.getTop(); // Math.max( _top, r.getTop() ); - _right = _right < r.getRight() ? _right : r.getRight(); // Math.min( _right, r.getRight() ); - _bottom = _bottom < r.getBottom() ? _bottom : r.getBottom(); // Math.min( _bottom, r.getBottom() ); - - resize(); - - }; - - /* - this.contains = function ( x, y ) { - - return x > _left && x < _right && y > _top && y < _bottom; - - }; - */ - - this.instersects = function ( r ) { - - // return this.contains( r.getLeft(), r.getTop() ) || this.contains( r.getRight(), r.getTop() ) || this.contains( r.getLeft(), r.getBottom() ) || this.contains( r.getRight(), r.getBottom() ); - - return Math.min( _right, r.getRight() ) - Math.max( _left, r.getLeft() ) >= 0 && - Math.min( _bottom, r.getBottom() ) - Math.max( _top, r.getTop() ) >= 0; - - }; - - this.empty = function () { - - _isEmpty = true; - - _left = 0; _top = 0; - _right = 0; _bottom = 0; - - resize(); - - }; - - this.isEmpty = function () { - - return _isEmpty; - - }; - -}; -THREE.Matrix3 = function () { - - this.m = []; - -}; - -THREE.Matrix3.prototype = { - - transpose : function () { - - var tmp, m = this.m; - - tmp = m[1]; m[1] = m[3]; m[3] = tmp; - tmp = m[2]; m[2] = m[6]; m[6] = tmp; - tmp = m[5]; m[5] = m[7]; m[7] = tmp; - - return this; - - }, - - transposeIntoArray : function ( r ) { - - var m = this.m; - - r[ 0 ] = m[ 0 ]; - r[ 1 ] = m[ 3 ]; - r[ 2 ] = m[ 6 ]; - r[ 3 ] = m[ 1 ]; - r[ 4 ] = m[ 4 ]; - r[ 5 ] = m[ 7 ]; - r[ 6 ] = m[ 2 ]; - r[ 7 ] = m[ 5 ]; - r[ 8 ] = m[ 8 ]; - - return this; - - } - -}; -/** - * @author mr.doob / http://mrdoob.com/ - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author philogb / http://blog.thejit.org/ - * @author jordi_ros / http://plattsoft.com - * @author D1plo1d / http://github.com/D1plo1d - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.Matrix4 = function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { - - this.set( - - n11 || 1, n12 || 0, n13 || 0, n14 || 0, - n21 || 0, n22 || 1, n23 || 0, n24 || 0, - n31 || 0, n32 || 0, n33 || 1, n34 || 0, - n41 || 0, n42 || 0, n43 || 0, n44 || 1 - - ); - - this.flat = new Array( 16 ); - this.m33 = new THREE.Matrix3(); - -}; - -THREE.Matrix4.prototype = { - - set : function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { - - this.n11 = n11; this.n12 = n12; this.n13 = n13; this.n14 = n14; - this.n21 = n21; this.n22 = n22; this.n23 = n23; this.n24 = n24; - this.n31 = n31; this.n32 = n32; this.n33 = n33; this.n34 = n34; - this.n41 = n41; this.n42 = n42; this.n43 = n43; this.n44 = n44; - - return this; - - }, - - identity : function () { - - this.set( - - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - copy : function ( m ) { - - this.set( - - m.n11, m.n12, m.n13, m.n14, - m.n21, m.n22, m.n23, m.n24, - m.n31, m.n32, m.n33, m.n34, - m.n41, m.n42, m.n43, m.n44 - - ); - - return this; - - }, - - lookAt : function ( eye, center, up ) { - - var x = THREE.Matrix4.__v1, y = THREE.Matrix4.__v2, z = THREE.Matrix4.__v3; - - z.sub( eye, center ).normalize(); - - if ( z.length() === 0 ) { - - z.z = 1; - - } - - x.cross( up, z ).normalize(); - - if ( x.length() === 0 ) { - - z.x += 0.0001; - x.cross( up, z ).normalize(); - - } - - y.cross( z, x ).normalize(); - - - this.n11 = x.x; this.n12 = y.x; this.n13 = z.x; - this.n21 = x.y; this.n22 = y.y; this.n23 = z.y; - this.n31 = x.z; this.n32 = y.z; this.n33 = z.z; - - return this; - - }, - - multiplyVector3 : function ( v ) { - - var vx = v.x, vy = v.y, vz = v.z, - d = 1 / ( this.n41 * vx + this.n42 * vy + this.n43 * vz + this.n44 ); - - v.x = ( this.n11 * vx + this.n12 * vy + this.n13 * vz + this.n14 ) * d; - v.y = ( this.n21 * vx + this.n22 * vy + this.n23 * vz + this.n24 ) * d; - v.z = ( this.n31 * vx + this.n32 * vy + this.n33 * vz + this.n34 ) * d; - - return v; - - }, - - multiplyVector4 : function ( v ) { - - var vx = v.x, vy = v.y, vz = v.z, vw = v.w; - - v.x = this.n11 * vx + this.n12 * vy + this.n13 * vz + this.n14 * vw; - v.y = this.n21 * vx + this.n22 * vy + this.n23 * vz + this.n24 * vw; - v.z = this.n31 * vx + this.n32 * vy + this.n33 * vz + this.n34 * vw; - v.w = this.n41 * vx + this.n42 * vy + this.n43 * vz + this.n44 * vw; - - return v; - - }, - - rotateAxis : function ( v ) { - - var vx = v.x, vy = v.y, vz = v.z; - - v.x = vx * this.n11 + vy * this.n12 + vz * this.n13; - v.y = vx * this.n21 + vy * this.n22 + vz * this.n23; - v.z = vx * this.n31 + vy * this.n32 + vz * this.n33; - - v.normalize(); - - return v; - - }, - - crossVector : function ( a ) { - - var v = new THREE.Vector4(); - - v.x = this.n11 * a.x + this.n12 * a.y + this.n13 * a.z + this.n14 * a.w; - v.y = this.n21 * a.x + this.n22 * a.y + this.n23 * a.z + this.n24 * a.w; - v.z = this.n31 * a.x + this.n32 * a.y + this.n33 * a.z + this.n34 * a.w; - - v.w = ( a.w ) ? this.n41 * a.x + this.n42 * a.y + this.n43 * a.z + this.n44 * a.w : 1; - - return v; - - }, - - multiply : function ( a, b ) { - - var a11 = a.n11, a12 = a.n12, a13 = a.n13, a14 = a.n14, - a21 = a.n21, a22 = a.n22, a23 = a.n23, a24 = a.n24, - a31 = a.n31, a32 = a.n32, a33 = a.n33, a34 = a.n34, - a41 = a.n41, a42 = a.n42, a43 = a.n43, a44 = a.n44, - - b11 = b.n11, b12 = b.n12, b13 = b.n13, b14 = b.n14, - b21 = b.n21, b22 = b.n22, b23 = b.n23, b24 = b.n24, - b31 = b.n31, b32 = b.n32, b33 = b.n33, b34 = b.n34, - b41 = b.n41, b42 = b.n42, b43 = b.n43, b44 = b.n44; - - this.n11 = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; - this.n12 = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; - this.n13 = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; - this.n14 = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; - - this.n21 = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; - this.n22 = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; - this.n23 = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; - this.n24 = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; - - this.n31 = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; - this.n32 = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; - this.n33 = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; - this.n34 = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; - - this.n41 = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; - this.n42 = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; - this.n43 = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; - this.n44 = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; - - return this; - - }, - - multiplyToArray : function ( a, b, r ) { - - this.multiply( a, b ); - - r[ 0 ] = this.n11; r[ 1 ] = this.n21; r[ 2 ] = this.n31; r[ 3 ] = this.n41; - r[ 4 ] = this.n12; r[ 5 ] = this.n22; r[ 6 ] = this.n32; r[ 7 ] = this.n42; - r[ 8 ] = this.n13; r[ 9 ] = this.n23; r[ 10 ] = this.n33; r[ 11 ] = this.n43; - r[ 12 ] = this.n14; r[ 13 ] = this.n24; r[ 14 ] = this.n34; r[ 15 ] = this.n44; - - return this; - - }, - - multiplySelf : function ( m ) { - - this.multiply( this, m ); - - return this; - - }, - - multiplyScalar : function ( s ) { - - this.n11 *= s; this.n12 *= s; this.n13 *= s; this.n14 *= s; - this.n21 *= s; this.n22 *= s; this.n23 *= s; this.n24 *= s; - this.n31 *= s; this.n32 *= s; this.n33 *= s; this.n34 *= s; - this.n41 *= s; this.n42 *= s; this.n43 *= s; this.n44 *= s; - - return this; - - }, - - determinant : function () { - - var n11 = this.n11, n12 = this.n12, n13 = this.n13, n14 = this.n14, - n21 = this.n21, n22 = this.n22, n23 = this.n23, n24 = this.n24, - n31 = this.n31, n32 = this.n32, n33 = this.n33, n34 = this.n34, - n41 = this.n41, n42 = this.n42, n43 = this.n43, n44 = this.n44; - - //TODO: make this more efficient - //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) - return ( - n14 * n23 * n32 * n41- - n13 * n24 * n32 * n41- - n14 * n22 * n33 * n41+ - n12 * n24 * n33 * n41+ - - n13 * n22 * n34 * n41- - n12 * n23 * n34 * n41- - n14 * n23 * n31 * n42+ - n13 * n24 * n31 * n42+ - - n14 * n21 * n33 * n42- - n11 * n24 * n33 * n42- - n13 * n21 * n34 * n42+ - n11 * n23 * n34 * n42+ - - n14 * n22 * n31 * n43- - n12 * n24 * n31 * n43- - n14 * n21 * n32 * n43+ - n11 * n24 * n32 * n43+ - - n12 * n21 * n34 * n43- - n11 * n22 * n34 * n43- - n13 * n22 * n31 * n44+ - n12 * n23 * n31 * n44+ - - n13 * n21 * n32 * n44- - n11 * n23 * n32 * n44- - n12 * n21 * n33 * n44+ - n11 * n22 * n33 * n44 - ); - - }, - - transpose : function () { - - var tmp; - - tmp = this.n21; this.n21 = this.n12; this.n12 = tmp; - tmp = this.n31; this.n31 = this.n13; this.n13 = tmp; - tmp = this.n32; this.n32 = this.n23; this.n23 = tmp; - - tmp = this.n41; this.n41 = this.n14; this.n14 = tmp; - tmp = this.n42; this.n42 = this.n24; this.n24 = tmp; - tmp = this.n43; this.n43 = this.n34; this.n43 = tmp; - - return this; - - }, - - clone : function () { - - var m = new THREE.Matrix4(); - - m.n11 = this.n11; m.n12 = this.n12; m.n13 = this.n13; m.n14 = this.n14; - m.n21 = this.n21; m.n22 = this.n22; m.n23 = this.n23; m.n24 = this.n24; - m.n31 = this.n31; m.n32 = this.n32; m.n33 = this.n33; m.n34 = this.n34; - m.n41 = this.n41; m.n42 = this.n42; m.n43 = this.n43; m.n44 = this.n44; - - return m; - - }, - - flatten : function () { - - this.flat[ 0 ] = this.n11; this.flat[ 1 ] = this.n21; this.flat[ 2 ] = this.n31; this.flat[ 3 ] = this.n41; - this.flat[ 4 ] = this.n12; this.flat[ 5 ] = this.n22; this.flat[ 6 ] = this.n32; this.flat[ 7 ] = this.n42; - this.flat[ 8 ] = this.n13; this.flat[ 9 ] = this.n23; this.flat[ 10 ] = this.n33; this.flat[ 11 ] = this.n43; - this.flat[ 12 ] = this.n14; this.flat[ 13 ] = this.n24; this.flat[ 14 ] = this.n34; this.flat[ 15 ] = this.n44; - - return this.flat; - - }, - - flattenToArray : function ( flat ) { - - flat[ 0 ] = this.n11; flat[ 1 ] = this.n21; flat[ 2 ] = this.n31; flat[ 3 ] = this.n41; - flat[ 4 ] = this.n12; flat[ 5 ] = this.n22; flat[ 6 ] = this.n32; flat[ 7 ] = this.n42; - flat[ 8 ] = this.n13; flat[ 9 ] = this.n23; flat[ 10 ] = this.n33; flat[ 11 ] = this.n43; - flat[ 12 ] = this.n14; flat[ 13 ] = this.n24; flat[ 14 ] = this.n34; flat[ 15 ] = this.n44; - - return flat; - - }, - - flattenToArrayOffset : function( flat, offset ) { - - flat[ offset ] = this.n11; - flat[ offset + 1 ] = this.n21; - flat[ offset + 2 ] = this.n31; - flat[ offset + 3 ] = this.n41; - - flat[ offset + 4 ] = this.n12; - flat[ offset + 5 ] = this.n22; - flat[ offset + 6 ] = this.n32; - flat[ offset + 7 ] = this.n42; - - flat[ offset + 8 ] = this.n13; - flat[ offset + 9 ] = this.n23; - flat[ offset + 10 ] = this.n33; - flat[ offset + 11 ] = this.n43; - - flat[ offset + 12 ] = this.n14; - flat[ offset + 13 ] = this.n24; - flat[ offset + 14 ] = this.n34; - flat[ offset + 15 ] = this.n44; - - return flat; - - }, - - setTranslation : function( x, y, z ) { - - this.set( - - 1, 0, 0, x, - 0, 1, 0, y, - 0, 0, 1, z, - 0, 0, 0, 1 - - ); - - return this; - - }, - - setScale : function ( x, y, z ) { - - this.set( - - x, 0, 0, 0, - 0, y, 0, 0, - 0, 0, z, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - setRotationX : function ( theta ) { - - var c = Math.cos( theta ), s = Math.sin( theta ); - - this.set( - - 1, 0, 0, 0, - 0, c, -s, 0, - 0, s, c, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - setRotationY : function( theta ) { - - var c = Math.cos( theta ), s = Math.sin( theta ); - - this.set( - - c, 0, s, 0, - 0, 1, 0, 0, - -s, 0, c, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - setRotationZ : function( theta ) { - - var c = Math.cos( theta ), s = Math.sin( theta ); - - this.set( - - c, -s, 0, 0, - s, c, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - setRotationAxis : function( axis, angle ) { - - // Based on http://www.gamedev.net/reference/articles/article1199.asp - - var c = Math.cos( angle ), - s = Math.sin( angle ), - t = 1 - c, - x = axis.x, y = axis.y, z = axis.z, - tx = t * x, ty = t * y; - - this.set( - - tx * x + c, tx * y - s * z, tx * z + s * y, 0, - tx * y + s * z, ty * y + c, ty * z - s * x, 0, - tx * z - s * y, ty * z + s * x, t * z * z + c, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - setPosition : function( v ) { - - this.n14 = v.x; - this.n24 = v.y; - this.n34 = v.z; - - return this; - - }, - - getPosition: function() { - - if ( ! this.position ) { - - this.position = new THREE.Vector3(); - - } - - this.position.set( this.n14, this.n24, this.n34 ); - - return this.position; - - }, - - getColumnX: function() { - - if ( ! this.columnX ) { - - this.columnX = new THREE.Vector3(); - - } - - this.columnX.set( this.n11, this.n21, this.n31 ); - - return this.columnX; - }, - - getColumnY: function() { - - if ( ! this.columnY ) { - - this.columnY = new THREE.Vector3(); - - } - - this.columnY.set( this.n12, this.n22, this.n32 ); - - return this.columnY; - - }, - - getColumnZ: function() { - - if ( ! this.columnZ ) { - - this.columnZ = new THREE.Vector3(); - - } - - this.columnZ.set( this.n13, this.n23, this.n33 ); - - return this.columnZ; - - }, - - setRotationFromEuler: function( v, order ) { - - var x = v.x, y = v.y, z = v.z, - a = Math.cos( x ), b = Math.sin( x ), - c = Math.cos( y ), d = Math.sin( y ), - e = Math.cos( z ), f = Math.sin( z ); - - switch ( order ) { - case 'YXZ': - var ce = c * e, cf = c * f, de = d * e, df = d * f; - - this.n11 = ce + df * b; - this.n12 = de * b - cf; - this.n13 = a * d; - - this.n21 = a * f; - this.n22 = a * e; - this.n23 = - b; - - this.n31 = cf * b - de; - this.n32 = df + ce * b; - this.n33 = a * c; - break; - - case 'ZXY': - var ce = c * e, cf = c * f, de = d * e, df = d * f; - - this.n11 = ce - df * b; - this.n12 = - a * f; - this.n13 = de + cf * b; - - this.n21 = cf + de * b; - this.n22 = a * e; - this.n23 = df - ce * b; - - this.n31 = - a * d; - this.n32 = b; - this.n33 = a * c; - break; - - case 'ZYX': - var ae = a * e, af = a * f, be = b * e, bf = b * f; - - this.n11 = c * e; - this.n12 = be * d - af; - this.n13 = ae * d + bf; - - this.n21 = c * f; - this.n22 = bf * d + ae; - this.n23 = af * d - be; - - this.n31 = - d; - this.n32 = b * c; - this.n33 = a * c; - break; - - case 'YZX': - var ac = a * c, ad = a * d, bc = b * c, bd = b * d; - - this.n11 = c * e; - this.n12 = bd - ac * f; - this.n13 = bc * f + ad; - - this.n21 = f; - this.n22 = a * e; - this.n23 = - b * e; - - this.n31 = - d * e; - this.n32 = ad * f + bc; - this.n33 = ac - bd * f; - break; - - case 'XZY': - var ac = a * c, ad = a * d, bc = b * c, bd = b * d; - - this.n11 = c * e; - this.n12 = - f; - this.n13 = d * e; - - this.n21 = ac * f + bd; - this.n22 = a * e; - this.n23 = ad * f - bc; - - this.n31 = bc * f - ad; - this.n32 = b * e; - this.n33 = bd * f + ac; - break; - - default: // 'XYZ' - var ae = a * e, af = a * f, be = b * e, bf = b * f; - - this.n11 = c * e; - this.n12 = - c * f; - this.n13 = d; - - this.n21 = af + be * d; - this.n22 = ae - bf * d; - this.n23 = - b * c; - - this.n31 = bf - ae * d; - this.n32 = be + af * d; - this.n33 = a * c; - break; - } - - return this; - - }, - - - setRotationFromQuaternion: function( q ) { - - var x = q.x, y = q.y, z = q.z, w = q.w, - x2 = x + x, y2 = y + y, z2 = z + z, - xx = x * x2, xy = x * y2, xz = x * z2, - yy = y * y2, yz = y * z2, zz = z * z2, - wx = w * x2, wy = w * y2, wz = w * z2; - - this.n11 = 1 - ( yy + zz ); - this.n12 = xy - wz; - this.n13 = xz + wy; - - this.n21 = xy + wz; - this.n22 = 1 - ( xx + zz ); - this.n23 = yz - wx; - - this.n31 = xz - wy; - this.n32 = yz + wx; - this.n33 = 1 - ( xx + yy ); - - return this; - - }, - - scale: function ( v ) { - - var x = v.x, y = v.y, z = v.z; - - this.n11 *= x; this.n12 *= y; this.n13 *= z; - this.n21 *= x; this.n22 *= y; this.n23 *= z; - this.n31 *= x; this.n32 *= y; this.n33 *= z; - this.n41 *= x; this.n42 *= y; this.n43 *= z; - - return this; - - }, - - extractPosition: function ( m ) { - - this.n14 = m.n14; - this.n24 = m.n24; - this.n34 = m.n34; - - }, - - extractRotation: function ( m, s ) { - - var invScaleX = 1 / s.x, invScaleY = 1 / s.y, invScaleZ = 1 / s.z; - - this.n11 = m.n11 * invScaleX; - this.n21 = m.n21 * invScaleX; - this.n31 = m.n31 * invScaleX; - - this.n12 = m.n12 * invScaleY; - this.n22 = m.n22 * invScaleY; - this.n32 = m.n32 * invScaleY; - - this.n13 = m.n13 * invScaleZ; - this.n23 = m.n23 * invScaleZ; - this.n33 = m.n33 * invScaleZ; - - } - -}; - -THREE.Matrix4.makeInvert = function ( m1, m2 ) { - - // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm - - var n11 = m1.n11, n12 = m1.n12, n13 = m1.n13, n14 = m1.n14, - n21 = m1.n21, n22 = m1.n22, n23 = m1.n23, n24 = m1.n24, - n31 = m1.n31, n32 = m1.n32, n33 = m1.n33, n34 = m1.n34, - n41 = m1.n41, n42 = m1.n42, n43 = m1.n43, n44 = m1.n44; - - if ( m2 === undefined ) m2 = new THREE.Matrix4(); - - m2.n11 = n23*n34*n42 - n24*n33*n42 + n24*n32*n43 - n22*n34*n43 - n23*n32*n44 + n22*n33*n44; - m2.n12 = n14*n33*n42 - n13*n34*n42 - n14*n32*n43 + n12*n34*n43 + n13*n32*n44 - n12*n33*n44; - m2.n13 = n13*n24*n42 - n14*n23*n42 + n14*n22*n43 - n12*n24*n43 - n13*n22*n44 + n12*n23*n44; - m2.n14 = n14*n23*n32 - n13*n24*n32 - n14*n22*n33 + n12*n24*n33 + n13*n22*n34 - n12*n23*n34; - m2.n21 = n24*n33*n41 - n23*n34*n41 - n24*n31*n43 + n21*n34*n43 + n23*n31*n44 - n21*n33*n44; - m2.n22 = n13*n34*n41 - n14*n33*n41 + n14*n31*n43 - n11*n34*n43 - n13*n31*n44 + n11*n33*n44; - m2.n23 = n14*n23*n41 - n13*n24*n41 - n14*n21*n43 + n11*n24*n43 + n13*n21*n44 - n11*n23*n44; - m2.n24 = n13*n24*n31 - n14*n23*n31 + n14*n21*n33 - n11*n24*n33 - n13*n21*n34 + n11*n23*n34; - m2.n31 = n22*n34*n41 - n24*n32*n41 + n24*n31*n42 - n21*n34*n42 - n22*n31*n44 + n21*n32*n44; - m2.n32 = n14*n32*n41 - n12*n34*n41 - n14*n31*n42 + n11*n34*n42 + n12*n31*n44 - n11*n32*n44; - m2.n33 = n13*n24*n41 - n14*n22*n41 + n14*n21*n42 - n11*n24*n42 - n12*n21*n44 + n11*n22*n44; - m2.n34 = n14*n22*n31 - n12*n24*n31 - n14*n21*n32 + n11*n24*n32 + n12*n21*n34 - n11*n22*n34; - m2.n41 = n23*n32*n41 - n22*n33*n41 - n23*n31*n42 + n21*n33*n42 + n22*n31*n43 - n21*n32*n43; - m2.n42 = n12*n33*n41 - n13*n32*n41 + n13*n31*n42 - n11*n33*n42 - n12*n31*n43 + n11*n32*n43; - m2.n43 = n13*n22*n41 - n12*n23*n41 - n13*n21*n42 + n11*n23*n42 + n12*n21*n43 - n11*n22*n43; - m2.n44 = n12*n23*n31 - n13*n22*n31 + n13*n21*n32 - n11*n23*n32 - n12*n21*n33 + n11*n22*n33; - m2.multiplyScalar( 1 / m1.determinant() ); - - return m2; - -}; - -THREE.Matrix4.makeInvert3x3 = function ( m1 ) { - - // input: THREE.Matrix4, output: THREE.Matrix3 - // ( based on http://code.google.com/p/webgl-mjs/ ) - - var m33 = m1.m33, m33m = m33.m, - a11 = m1.n33 * m1.n22 - m1.n32 * m1.n23, - a21 = - m1.n33 * m1.n21 + m1.n31 * m1.n23, - a31 = m1.n32 * m1.n21 - m1.n31 * m1.n22, - a12 = - m1.n33 * m1.n12 + m1.n32 * m1.n13, - a22 = m1.n33 * m1.n11 - m1.n31 * m1.n13, - a32 = - m1.n32 * m1.n11 + m1.n31 * m1.n12, - a13 = m1.n23 * m1.n12 - m1.n22 * m1.n13, - a23 = - m1.n23 * m1.n11 + m1.n21 * m1.n13, - a33 = m1.n22 * m1.n11 - m1.n21 * m1.n12, - - det = m1.n11 * a11 + m1.n21 * a12 + m1.n31 * a13, - - idet; - - // no inverse - if ( det == 0 ) { - - console.error( 'THREE.Matrix4.makeInvert3x3: Matrix not invertible.' ); - - } - - idet = 1.0 / det; - - m33m[ 0 ] = idet * a11; m33m[ 1 ] = idet * a21; m33m[ 2 ] = idet * a31; - m33m[ 3 ] = idet * a12; m33m[ 4 ] = idet * a22; m33m[ 5 ] = idet * a32; - m33m[ 6 ] = idet * a13; m33m[ 7 ] = idet * a23; m33m[ 8 ] = idet * a33; - - return m33; - -} - -THREE.Matrix4.makeFrustum = function ( left, right, bottom, top, near, far ) { - - var m, x, y, a, b, c, d; - - m = new THREE.Matrix4(); - x = 2 * near / ( right - left ); - y = 2 * near / ( top - bottom ); - a = ( right + left ) / ( right - left ); - b = ( top + bottom ) / ( top - bottom ); - c = - ( far + near ) / ( far - near ); - d = - 2 * far * near / ( far - near ); - - m.n11 = x; m.n12 = 0; m.n13 = a; m.n14 = 0; - m.n21 = 0; m.n22 = y; m.n23 = b; m.n24 = 0; - m.n31 = 0; m.n32 = 0; m.n33 = c; m.n34 = d; - m.n41 = 0; m.n42 = 0; m.n43 = - 1; m.n44 = 0; - - return m; - -}; - -THREE.Matrix4.makePerspective = function ( fov, aspect, near, far ) { - - var ymax, ymin, xmin, xmax; - - ymax = near * Math.tan( fov * Math.PI / 360 ); - ymin = - ymax; - xmin = ymin * aspect; - xmax = ymax * aspect; - - return THREE.Matrix4.makeFrustum( xmin, xmax, ymin, ymax, near, far ); - -}; - -THREE.Matrix4.makeOrtho = function ( left, right, top, bottom, near, far ) { - - var m, x, y, z, w, h, p; - - m = new THREE.Matrix4(); - w = right - left; - h = top - bottom; - p = far - near; - x = ( right + left ) / w; - y = ( top + bottom ) / h; - z = ( far + near ) / p; - - m.n11 = 2 / w; m.n12 = 0; m.n13 = 0; m.n14 = -x; - m.n21 = 0; m.n22 = 2 / h; m.n23 = 0; m.n24 = -y; - m.n31 = 0; m.n32 = 0; m.n33 = -2 / p; m.n34 = -z; - m.n41 = 0; m.n42 = 0; m.n43 = 0; m.n44 = 1; - - return m; - -}; - -THREE.Matrix4.__v1 = new THREE.Vector3(); -THREE.Matrix4.__v2 = new THREE.Vector3(); -THREE.Matrix4.__v3 = new THREE.Vector3(); -/** - * @author mr.doob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.Object3D = function() { - - this.parent = undefined; - this.children = []; - - this.up = new THREE.Vector3( 0, 1, 0 ); - - this.position = new THREE.Vector3(); - this.rotation = new THREE.Vector3(); - this.eulerOrder = 'XYZ'; - this.scale = new THREE.Vector3( 1, 1, 1 ); - - this.dynamic = false; // when true it retains arrays so they can be updated with __dirty* - - this.doubleSided = false; - this.flipSided = false; - - this.renderDepth = null; - - this.rotationAutoUpdate = true; - - this.matrix = new THREE.Matrix4(); - this.matrixWorld = new THREE.Matrix4(); - this.matrixRotationWorld = new THREE.Matrix4(); - - this.matrixAutoUpdate = true; - this.matrixWorldNeedsUpdate = true; - - this.quaternion = new THREE.Quaternion(); - this.useQuaternion = false; - - this.boundRadius = 0.0; - this.boundRadiusScale = 1.0; - - this.visible = true; - - this._vector = new THREE.Vector3(); - - this.name = ""; - -}; - - -THREE.Object3D.prototype = { - - translate : function ( distance, axis ) { - - this.matrix.rotateAxis( axis ); - this.position.addSelf( axis.multiplyScalar( distance ) ); - - }, - - translateX : function ( distance ) { - - this.translate( distance, this._vector.set( 1, 0, 0 ) ); - - }, - - translateY : function ( distance ) { - - this.translate( distance, this._vector.set( 0, 1, 0 ) ); - - }, - - translateZ : function ( distance ) { - - this.translate( distance, this._vector.set( 0, 0, 1 ) ); - - }, - - lookAt : function ( vector ) { - - // TODO: Add hierarchy support. - - this.matrix.lookAt( vector, this.position, this.up ); - - if ( this.rotationAutoUpdate ) { - - this.rotation.setRotationFromMatrix( this.matrix ); - - } - - }, - - addChild: function ( child ) { - - if ( this.children.indexOf( child ) === - 1 ) { - - if( child.parent !== undefined ) { - - child.parent.removeChild( child ); - - } - - child.parent = this; - this.children.push( child ); - - // add to scene - - var scene = this; - - while ( scene.parent !== undefined ) { - - scene = scene.parent; - - } - - if ( scene !== undefined && scene instanceof THREE.Scene ) { - - scene.addChildRecurse( child ); - - } - - } - - }, - - removeChild: function ( child ) { - - var childIndex = this.children.indexOf( child ); - - if ( childIndex !== - 1 ) { - - child.parent = undefined; - this.children.splice( childIndex, 1 ); - - } - - }, - - getChildByName: function ( name, doRecurse ) { - - var c, cl, child, recurseResult; - - for ( c = 0, cl = this.children.length; c < cl; c++ ) { - - child = this.children[ c ]; - - if ( child.name === name ) { - - return child; - - } - - if ( doRecurse ) { - - recurseResult = child.getChildByName( name, doRecurse ); - - if ( recurseResult !== undefined ) { - - return recurseResult; - - } - - } - - } - - return undefined; - - }, - - updateMatrix: function () { - - this.matrix.setPosition( this.position ); - - if ( this.useQuaternion ) { - - this.matrix.setRotationFromQuaternion( this.quaternion ); - - } else { - - this.matrix.setRotationFromEuler( this.rotation, this.eulerOrder ); - - } - - if ( this.scale.x !== 1 || this.scale.y !== 1 || this.scale.z !== 1 ) { - - this.matrix.scale( this.scale ); - this.boundRadiusScale = Math.max( this.scale.x, Math.max( this.scale.y, this.scale.z ) ); - - } - - this.matrixWorldNeedsUpdate = true; - - }, - - update: function ( parentMatrixWorld, forceUpdate, camera ) { - - this.matrixAutoUpdate && this.updateMatrix(); - - // update matrixWorld - - if ( this.matrixWorldNeedsUpdate || forceUpdate ) { - - if ( parentMatrixWorld ) { - - this.matrixWorld.multiply( parentMatrixWorld, this.matrix ); - - } else { - - this.matrixWorld.copy( this.matrix ); - - } - - this.matrixRotationWorld.extractRotation( this.matrixWorld, this.scale ); - - this.matrixWorldNeedsUpdate = false; - - forceUpdate = true; - - } - - // update children - - for ( var i = 0, l = this.children.length; i < l; i ++ ) { - - this.children[ i ].update( this.matrixWorld, forceUpdate, camera ); - - } - - } - -}; -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.Quaternion = function( x, y, z, w ) { - - this.set( - - x || 0, - y || 0, - z || 0, - w !== undefined ? w : 1 - - ); - -}; - -THREE.Quaternion.prototype = { - - set : function ( x, y, z, w ) { - - this.x = x; - this.y = y; - this.z = z; - this.w = w; - - return this; - - }, - - copy : function ( q ) { - - this.x = q.x; - this.y = q.y; - this.z = q.z; - this.w = q.w; - - return this; - - }, - - setFromEuler : function ( vec3 ) { - - var c = 0.5 * Math.PI / 360, // 0.5 is an optimization - x = vec3.x * c, - y = vec3.y * c, - z = vec3.z * c, - - c1 = Math.cos( y ), - s1 = Math.sin( y ), - c2 = Math.cos( -z ), - s2 = Math.sin( -z ), - c3 = Math.cos( x ), - s3 = Math.sin( x ), - - c1c2 = c1 * c2, - s1s2 = s1 * s2; - - this.w = c1c2 * c3 - s1s2 * s3; - this.x = c1c2 * s3 + s1s2 * c3; - this.y = s1 * c2 * c3 + c1 * s2 * s3; - this.z = c1 * s2 * c3 - s1 * c2 * s3; - - return this; - - }, - - setFromAxisAngle: function ( axis, angle ) { - - // from http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm - // axis have to be normalized - - var halfAngle = angle / 2, - s = Math.sin( halfAngle ); - - this.x = axis.x * s; - this.y = axis.y * s; - this.z = axis.z * s; - this.w = Math.cos( halfAngle ); - - return this; - - }, - - calculateW : function () { - - this.w = - Math.sqrt( Math.abs( 1.0 - this.x * this.x - this.y * this.y - this.z * this.z ) ); - - return this; - - }, - - inverse : function () { - - this.x *= -1; - this.y *= -1; - this.z *= -1; - - return this; - - }, - - length : function () { - - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - - }, - - normalize : function () { - - var l = Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - - if ( l == 0 ) { - - this.x = 0; - this.y = 0; - this.z = 0; - this.w = 0; - - } else { - - l = 1 / l; - - this.x = this.x * l; - this.y = this.y * l; - this.z = this.z * l; - this.w = this.w * l; - - } - - return this; - - }, - - multiplySelf : function ( quat2 ) { - - var qax = this.x, qay = this.y, qaz = this.z, qaw = this.w, - qbx = quat2.x, qby = quat2.y, qbz = quat2.z, qbw = quat2.w; - - this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; - this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; - this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; - this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; - - return this; - - }, - - multiply: function ( q1, q2 ) { - - // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - - this.x = q1.x * q2.w + q1.y * q2.z - q1.z * q2.y + q1.w * q2.x; - this.y = -q1.x * q2.z + q1.y * q2.w + q1.z * q2.x + q1.w * q2.y; - this.z = q1.x * q2.y - q1.y * q2.x + q1.z * q2.w + q1.w * q2.z; - this.w = -q1.x * q2.x - q1.y * q2.y - q1.z * q2.z + q1.w * q2.w; - - return this; - - }, - - multiplyVector3 : function ( vec, dest ) { - - if( !dest ) { dest = vec; } - - var x = vec.x, y = vec.y, z = vec.z, - qx = this.x, qy = this.y, qz = this.z, qw = this.w; - - // calculate quat * vec - - var ix = qw * x + qy * z - qz * y, - iy = qw * y + qz * x - qx * z, - iz = qw * z + qx * y - qy * x, - iw = -qx * x - qy * y - qz * z; - - // calculate result * inverse quat - - dest.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; - dest.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; - dest.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; - - return dest; - - } - -} - -THREE.Quaternion.slerp = function ( qa, qb, qm, t ) { - - var cosHalfTheta = qa.w * qb.w + qa.x * qb.x + qa.y * qb.y + qa.z * qb.z; - - if ( Math.abs( cosHalfTheta ) >= 1.0 ) { - - qm.w = qa.w; qm.x = qa.x; qm.y = qa.y; qm.z = qa.z; - return qm; - - } - - var halfTheta = Math.acos( cosHalfTheta ), - sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta ); - - if ( Math.abs( sinHalfTheta ) < 0.001 ) { - - qm.w = 0.5 * ( qa.w + qb.w ); - qm.x = 0.5 * ( qa.x + qb.x ); - qm.y = 0.5 * ( qa.y + qb.y ); - qm.z = 0.5 * ( qa.z + qb.z ); - - return qm; - - } - - var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, - ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; - - qm.w = ( qa.w * ratioA + qb.w * ratioB ); - qm.x = ( qa.x * ratioA + qb.x * ratioB ); - qm.y = ( qa.y * ratioA + qb.y * ratioB ); - qm.z = ( qa.z * ratioA + qb.z * ratioB ); - - return qm; - -} -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.Vertex = function ( position ) { - - this.position = position || new THREE.Vector3(); - -}; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.Face3 = function ( a, b, c, normal, color, materials ) { - - this.a = a; - this.b = b; - this.c = c; - - this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3(); - this.vertexNormals = normal instanceof Array ? normal : [ ]; - - this.color = color instanceof THREE.Color ? color : new THREE.Color(); - this.vertexColors = color instanceof Array ? color : []; - - this.vertexTangents = []; - - this.materials = materials instanceof Array ? materials : [ materials ]; - - this.centroid = new THREE.Vector3(); - -}; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.Face4 = function ( a, b, c, d, normal, color, materials ) { - - this.a = a; - this.b = b; - this.c = c; - this.d = d; - - this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3(); - this.vertexNormals = normal instanceof Array ? normal : [ ]; - - this.color = color instanceof THREE.Color ? color : new THREE.Color(); - this.vertexColors = color instanceof Array ? color : []; - - this.vertexTangents = []; - - this.materials = materials instanceof Array ? materials : [ materials ]; - - this.centroid = new THREE.Vector3(); - -}; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.UV = function ( u, v ) { - - this.set( - - u || 0, - v || 0 - - ); - -}; - -THREE.UV.prototype = { - - set : function ( u, v ) { - - this.u = u; - this.v = v; - - return this; - - }, - - copy : function ( uv ) { - - this.set( - - uv.u, - uv.v - - ); - - return this; - - } - -}; -/** - * @author mr.doob / http://mrdoob.com/ - * @author kile / http://kile.stravaganza.org/ - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.Geometry = function () { - - this.id = "Geometry" + THREE.GeometryIdCounter ++; - - this.vertices = []; - this.colors = []; // one-to-one vertex colors, used in ParticleSystem, Line and Ribbon - - this.faces = []; - - this.edges = []; - - this.faceUvs = [[]]; - this.faceVertexUvs = [[]]; - - this.morphTargets = []; - this.morphColors = []; - - this.skinWeights = []; - this.skinIndices = []; - - this.boundingBox = null; - this.boundingSphere = null; - - this.hasTangents = false; - -}; - -THREE.Geometry.prototype = { - - computeCentroids: function () { - - var f, fl, face; - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - face.centroid.set( 0, 0, 0 ); - - if ( face instanceof THREE.Face3 ) { - - face.centroid.addSelf( this.vertices[ face.a ].position ); - face.centroid.addSelf( this.vertices[ face.b ].position ); - face.centroid.addSelf( this.vertices[ face.c ].position ); - face.centroid.divideScalar( 3 ); - - } else if ( face instanceof THREE.Face4 ) { - - face.centroid.addSelf( this.vertices[ face.a ].position ); - face.centroid.addSelf( this.vertices[ face.b ].position ); - face.centroid.addSelf( this.vertices[ face.c ].position ); - face.centroid.addSelf( this.vertices[ face.d ].position ); - face.centroid.divideScalar( 4 ); - - } - - } - - }, - - computeFaceNormals: function ( useVertexNormals ) { - - var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC, - cb = new THREE.Vector3(), ab = new THREE.Vector3(); - - /* - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - - vertex = this.vertices[ v ]; - vertex.normal.set( 0, 0, 0 ); - - } - */ - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - if ( useVertexNormals && face.vertexNormals.length ) { - - cb.set( 0, 0, 0 ); - - for ( n = 0, nl = face.vertexNormals.length; n < nl; n++ ) { - - cb.addSelf( face.vertexNormals[n] ); - - } - - cb.divideScalar( 3 ); - - if ( ! cb.isZero() ) { - - cb.normalize(); - - } - - face.normal.copy( cb ); - - } else { - - vA = this.vertices[ face.a ]; - vB = this.vertices[ face.b ]; - vC = this.vertices[ face.c ]; - - cb.sub( vC.position, vB.position ); - ab.sub( vA.position, vB.position ); - cb.crossSelf( ab ); - - if ( !cb.isZero() ) { - - cb.normalize(); - - } - - face.normal.copy( cb ); - - } - - } - - }, - - computeVertexNormals: function () { - - var v, vl, f, fl, face, vertices; - - // create internal buffers for reuse when calling this method repeatedly - // (otherwise memory allocation / deallocation every frame is big resource hog) - - if ( this.__tmpVertices == undefined ) { - - this.__tmpVertices = new Array( this.vertices.length ); - vertices = this.__tmpVertices; - - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - - vertices[ v ] = new THREE.Vector3(); - - } - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - if ( face instanceof THREE.Face3 ) { - - face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ]; - - } else if ( face instanceof THREE.Face4 ) { - - face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ]; - - } - - } - - } else { - - vertices = this.__tmpVertices; - - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - - vertices[ v ].set( 0, 0, 0 ); - - } - - } - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - if ( face instanceof THREE.Face3 ) { - - vertices[ face.a ].addSelf( face.normal ); - vertices[ face.b ].addSelf( face.normal ); - vertices[ face.c ].addSelf( face.normal ); - - } else if ( face instanceof THREE.Face4 ) { - - vertices[ face.a ].addSelf( face.normal ); - vertices[ face.b ].addSelf( face.normal ); - vertices[ face.c ].addSelf( face.normal ); - vertices[ face.d ].addSelf( face.normal ); - - } - - } - - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - - vertices[ v ].normalize(); - - } - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - if ( face instanceof THREE.Face3 ) { - - face.vertexNormals[ 0 ].copy( vertices[ face.a ] ); - face.vertexNormals[ 1 ].copy( vertices[ face.b ] ); - face.vertexNormals[ 2 ].copy( vertices[ face.c ] ); - - } else if ( face instanceof THREE.Face4 ) { - - face.vertexNormals[ 0 ].copy( vertices[ face.a ] ); - face.vertexNormals[ 1 ].copy( vertices[ face.b ] ); - face.vertexNormals[ 2 ].copy( vertices[ face.c ] ); - face.vertexNormals[ 3 ].copy( vertices[ face.d ] ); - - } - - } - - }, - - 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; - - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - - tan1[ v ] = new THREE.Vector3(); - tan2[ v ] = new THREE.Vector3(); - - } - - function handleTriangle( context, a, b, c, ua, ub, uc ) { - - vA = context.vertices[ a ].position; - vB = context.vertices[ b ].position; - vC = context.vertices[ c ].position; - - uvA = uv[ ua ]; - uvB = uv[ ub ]; - uvC = uv[ uc ]; - - 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.u - uvA.u; - s2 = uvC.u - uvA.u; - t1 = uvB.v - uvA.v; - t2 = uvC.v - uvA.v; - - r = 1.0 / ( s1 * t2 - s2 * t1 ); - sdir.set( ( t2 * x1 - t1 * x2 ) * r, - ( t2 * y1 - t1 * y2 ) * r, - ( t2 * z1 - t1 * z2 ) * r ); - tdir.set( ( s1 * x2 - s2 * x1 ) * r, - ( s1 * y2 - s2 * y1 ) * r, - ( s1 * z2 - s2 * z1 ) * r ); - - tan1[ a ].addSelf( sdir ); - tan1[ b ].addSelf( sdir ); - tan1[ c ].addSelf( sdir ); - - tan2[ a ].addSelf( tdir ); - tan2[ b ].addSelf( tdir ); - tan2[ c ].addSelf( 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 - - if ( face instanceof THREE.Face3 ) { - - handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 ); - - } else if ( face instanceof THREE.Face4 ) { - - handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 ); - handleTriangle( this, face.a, face.b, face.d, 0, 1, 3 ); - - } - - } - - var faceIndex = [ 'a', 'b', 'c', 'd' ]; - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - for ( i = 0; i < face.vertexNormals.length; i++ ) { - - n.copy( face.vertexNormals[ i ] ); - - vertexIndex = face[ faceIndex[ i ] ]; - - t = tan1[ vertexIndex ]; - - // Gram-Schmidt orthogonalize - - tmp.copy( t ); - tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize(); - - // Calculate handedness - - tmp2.cross( face.vertexNormals[ i ], t ); - test = tmp2.dot( tan2[ vertexIndex ] ); - w = (test < 0.0) ? -1.0 : 1.0; - - face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w ); - - } - - } - - this.hasTangents = true; - - }, - - computeBoundingBox: function () { - - var vertex; - - if ( this.vertices.length > 0 ) { - - this.boundingBox = { 'x': [ this.vertices[ 0 ].position.x, this.vertices[ 0 ].position.x ], - 'y': [ this.vertices[ 0 ].position.y, this.vertices[ 0 ].position.y ], - 'z': [ this.vertices[ 0 ].position.z, this.vertices[ 0 ].position.z ] }; - - for ( var v = 1, vl = this.vertices.length; v < vl; v ++ ) { - - vertex = this.vertices[ v ]; - - if ( vertex.position.x < this.boundingBox.x[ 0 ] ) { - - this.boundingBox.x[ 0 ] = vertex.position.x; - - } else if ( vertex.position.x > this.boundingBox.x[ 1 ] ) { - - this.boundingBox.x[ 1 ] = vertex.position.x; - - } - - if ( vertex.position.y < this.boundingBox.y[ 0 ] ) { - - this.boundingBox.y[ 0 ] = vertex.position.y; - - } else if ( vertex.position.y > this.boundingBox.y[ 1 ] ) { - - this.boundingBox.y[ 1 ] = vertex.position.y; - - } - - if ( vertex.position.z < this.boundingBox.z[ 0 ] ) { - - this.boundingBox.z[ 0 ] = vertex.position.z; - - } else if ( vertex.position.z > this.boundingBox.z[ 1 ] ) { - - this.boundingBox.z[ 1 ] = vertex.position.z; - - } - - } - - } - - }, - - computeBoundingSphere: function () { - - // var radius = this.boundingSphere === null ? 0 : this.boundingSphere.radius; - - var radius = 0; - - for ( var v = 0, vl = this.vertices.length; v < vl; v ++ ) { - - radius = Math.max( radius, this.vertices[ v ].position.length() ); - - } - - this.boundingSphere = { radius: radius }; - - }, - - computeEdgeFaces: function () { - - function edge_hash( a, b ) { - - return Math.min( a, b ) + "_" + Math.max( a, b ); - - }; - - function addToMap( map, hash, i ) { - - if ( map[ hash ] === undefined ) { - - map[ hash ] = { "set": {}, "array": [] }; - map[ hash ].set[ i ] = 1; - map[ hash ].array.push( i ); - - } else { - - if( map[ hash ].set[ i ] === undefined ) { - - map[ hash ].set[ i ] = 1; - map[ hash ].array.push( i ); - - } - - } - - }; - - var i, il, v1, v2, j, k, - face, faceIndices, faceIndex, - edge, - hash, - vfMap = {}; - - // construct vertex -> face map - - for( i = 0, il = this.faces.length; i < il; i ++ ) { - - face = this.faces[ i ]; - - if ( face instanceof THREE.Face3 ) { - - hash = edge_hash( face.a, face.b ); - addToMap( vfMap, hash, i ); - - hash = edge_hash( face.b, face.c ); - addToMap( vfMap, hash, i ); - - hash = edge_hash( face.a, face.c ); - addToMap( vfMap, hash, i ); - - } else if ( face instanceof THREE.Face4 ) { - - // in WebGLRenderer quad is tesselated - // to triangles: a,b,d / b,c,d - // shared edge is: b,d - - // should shared edge be included? - // comment out if not - - hash = edge_hash( face.b, face.d ); - addToMap( vfMap, hash, i ); - - hash = edge_hash( face.a, face.b ); - addToMap( vfMap, hash, i ); - - hash = edge_hash( face.a, face.d ); - addToMap( vfMap, hash, i ); - - hash = edge_hash( face.b, face.c ); - addToMap( vfMap, hash, i ); - - hash = edge_hash( face.c, face.d ); - addToMap( vfMap, hash, i ); - - } - - } - - // extract faces - - for( i = 0, il = this.edges.length; i < il; i ++ ) { - - edge = this.edges[ i ]; - - v1 = edge.vertexIndices[ 0 ]; - v2 = edge.vertexIndices[ 1 ]; - - edge.faceIndices = vfMap[ edge_hash( v1, v2 ) ].array; - - for( j = 0; j < edge.faceIndices.length; j ++ ) { - - faceIndex = edge.faceIndices[ j ]; - edge.faces.push( this.faces[ faceIndex ] ); - - } - - } - - } - -}; - -THREE.GeometryIdCounter = 0; -/** - * Spline from Tween.js, slightly optimized (and trashed) - * http://sole.github.com/tween.js/examples/05_spline.html - * - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.Spline = function ( points ) { - - this.points = points; - - var c = [], v3 = { x: 0, y: 0, z: 0 }, - point, intPoint, weight, w2, w3, - pa, pb, pc, pd; - - this.initFromArray = function( a ) { - - this.points = []; - - for ( var i = 0; i < a.length; i++ ) { - - this.points[ i ] = { x: a[ i ][ 0 ], y: a[ i ][ 1 ], z: a[ i ][ 2 ] }; - - } - - }; - - this.getPoint = function ( k ) { - - point = ( this.points.length - 1 ) * k; - intPoint = Math.floor( point ); - weight = point - intPoint; - - c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1; - c[ 1 ] = intPoint; - c[ 2 ] = intPoint > this.points.length - 2 ? intPoint : intPoint + 1; - c[ 3 ] = intPoint > this.points.length - 3 ? intPoint : intPoint + 2; - - pa = this.points[ c[ 0 ] ]; - pb = this.points[ c[ 1 ] ]; - pc = this.points[ c[ 2 ] ]; - pd = this.points[ c[ 3 ] ]; - - w2 = weight * weight; - w3 = weight * w2; - - v3.x = interpolate( pa.x, pb.x, pc.x, pd.x, weight, w2, w3 ); - v3.y = interpolate( pa.y, pb.y, pc.y, pd.y, weight, w2, w3 ); - v3.z = interpolate( pa.z, pb.z, pc.z, pd.z, weight, w2, w3 ); - - return v3; - - }; - - this.getControlPointsArray = function () { - - var i, p, l = this.points.length, - coords = []; - - for ( i = 0; i < l; i ++ ) { - - p = this.points[ i ]; - coords[ i ] = [ p.x, p.y, p.z ]; - - } - - return coords; - - }; - - // approximate length by summing linear segments - - this.getLength = function ( nSubDivisions ) { - - var i, index, nSamples, - point = 0, intPoint = 0, oldIntPoint = 0, - oldPosition = new THREE.Vector3(), - tmpVec = new THREE.Vector3(), - chunkLengths = [], - totalLength = 0; - - // first point has 0 length - - chunkLengths[ 0 ] = 0; - - if ( !nSubDivisions ) nSubDivisions = 100; - - nSamples = this.points.length * nSubDivisions; - - oldPosition.copy( this.points[ 0 ] ); - - for ( i = 1; i < nSamples; i ++ ) { - - index = i / nSamples; - - position = this.getPoint( index ); - tmpVec.copy( position ); - - totalLength += tmpVec.distanceTo( oldPosition ); - - oldPosition.copy( position ); - - point = ( this.points.length - 1 ) * index; - intPoint = Math.floor( point ); - - if ( intPoint != oldIntPoint ) { - - chunkLengths[ intPoint ] = totalLength; - oldIntPoint = intPoint; - - } - - } - - // last point ends with total length - - chunkLengths[ chunkLengths.length ] = totalLength; - - return { chunks: chunkLengths, total: totalLength }; - - }; - - this.reparametrizeByArcLength = function ( samplingCoef ) { - - var i, j, - index, indexCurrent, indexNext, - linearDistance, realDistance, - sampling, - newpoints = [], - tmpVec = new THREE.Vector3(), - sl = this.getLength(); - - newpoints.push( tmpVec.copy( this.points[ 0 ] ).clone() ); - - for ( i = 1; i < this.points.length; i++ ) { - - //tmpVec.copy( this.points[ i - 1 ] ); - //linearDistance = tmpVec.distanceTo( this.points[ i ] ); - - realDistance = sl.chunks[ i ] - sl.chunks[ i - 1 ]; - - sampling = Math.ceil( samplingCoef * realDistance / sl.total ); - - indexCurrent = ( i - 1 ) / ( this.points.length - 1 ); - indexNext = i / ( this.points.length - 1 ); - - for ( j = 1; j < sampling - 1; j++ ) { - - index = indexCurrent + j * ( 1 / sampling ) * ( indexNext - indexCurrent ); - - position = this.getPoint( index ); - newpoints.push( tmpVec.copy( position ).clone() ); - - } - - newpoints.push( tmpVec.copy( this.points[ i ] ).clone() ); - - } - - this.points = newpoints; - - }; - - // Catmull-Rom - - function interpolate( p0, p1, p2, p3, t, t2, t3 ) { - - var v0 = ( p2 - p0 ) * 0.5, - v1 = ( p3 - p1 ) * 0.5; - - return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1; - - }; - -}; -/** - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.Edge = function( v1, v2, vi1, vi2 ) { - - this.vertices = [ v1, v2 ]; // vertex references - this.vertexIndices = [ vi1, vi2 ]; // vertex indices - - this.faces = []; // face references - this.faceIndices = []; // face indices - -}; -/** - * @author mr.doob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - * @author greggman / http://games.greggman.com/ - */ - -THREE.Camera = function ( fov, aspect, near, far, target ) { - - THREE.Object3D.call( this ); - - this.fov = fov || 50; - this.aspect = aspect || 1; - this.near = near || 0.1; - this.far = far || 2000; - - this.target = target || new THREE.Object3D(); - this.useTarget = true; - - this.matrixWorldInverse = new THREE.Matrix4(); - this.projectionMatrix = null; - - this.updateProjectionMatrix(); - -}; - -THREE.Camera.prototype = new THREE.Object3D(); -THREE.Camera.prototype.constructor = THREE.Camera; -THREE.Camera.prototype.supr = THREE.Object3D.prototype; - - -THREE.Camera.prototype.translate = function ( distance, axis ) { - - this.matrix.rotateAxis( axis ); - - axis.multiplyScalar( distance ) - - this.position.addSelf( axis ); - this.target.position.addSelf( axis ); - -}; - - -THREE.Camera.prototype.updateProjectionMatrix = function () { - - if ( this.fullWidth ) { - - var aspect = this.fullWidth / this.fullHeight; - var top = Math.tan( this.fov * Math.PI / 360 ) * this.near; - var bottom = -top; - var left = aspect * bottom; - var right = aspect * top; - var width = Math.abs( right - left ); - var height = Math.abs( top - bottom ); - - this.projectionMatrix = THREE.Matrix4.makeFrustum( - left + this.x * width / this.fullWidth, - left + ( this.x + this.width ) * width / this.fullWidth, - top - ( this.y + this.height ) * height / this.fullHeight, - top - this.y * height / this.fullHeight, - this.near, - this.far ); - - } else { - - this.projectionMatrix = THREE.Matrix4.makePerspective( this.fov, this.aspect, this.near, this.far ); - - } - -}; - -/** - * Sets an offset in a larger frustum. This is useful for multi-window or - * multi-monitor/multi-machine setups. - * - * For example, if you have 3x2 monitors and each monitor is 1920x1080 and - * the monitors are in grid like this - * - * +---+---+---+ - * | A | B | C | - * +---+---+---+ - * | D | E | F | - * +---+---+---+ - * - * then for monitor each monitor you would call it like this - * - * var w = 1920; - * var h = 1080; - * var fullWidth = w * 3; - * var fullHeight = h * 2; - * - * --A-- - * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); - * --B-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); - * --C-- - * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); - * --D-- - * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); - * --E-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); - * --F-- - * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); - * - * Note there is no reason monitors have to be the same size or in a grid. - */ - -THREE.Camera.prototype.setViewOffset = function( fullWidth, fullHeight, x, y, width, height ) { - - this.fullWidth = fullWidth; - this.fullHeight = fullHeight; - this.x = x; - this.y = y; - this.width = width; - this.height = height; - - this.updateProjectionMatrix(); - -}; - -THREE.Camera.prototype.update = function ( parentMatrixWorld, forceUpdate, camera ) { - - if ( this.useTarget ) { - - // local - - this.matrix.lookAt( this.position, this.target.position, this.up ); - this.matrix.setPosition( this.position ); - - - // global - - if( parentMatrixWorld ) { - - this.matrixWorld.multiply( parentMatrixWorld, this.matrix ); - - } else { - - this.matrixWorld.copy( this.matrix ); - - } - - THREE.Matrix4.makeInvert( this.matrixWorld, this.matrixWorldInverse ); - - forceUpdate = true; - - } else { - - this.matrixAutoUpdate && this.updateMatrix(); - - if ( forceUpdate || this.matrixWorldNeedsUpdate ) { - - if ( parentMatrixWorld ) { - - this.matrixWorld.multiply( parentMatrixWorld, this.matrix ); - - } else { - - this.matrixWorld.copy( this.matrix ); - - } - - this.matrixWorldNeedsUpdate = false; - forceUpdate = true; - - THREE.Matrix4.makeInvert( this.matrixWorld, this.matrixWorldInverse ); - - } - - } - - // update children - - for ( var i = 0; i < this.children.length; i ++ ) { - - this.children[ i ].update( this.matrixWorld, forceUpdate, camera ); - - } - -}; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.Light = function ( hex ) { - - THREE.Object3D.call( this ); - - this.color = new THREE.Color( hex ); - -}; - -THREE.Light.prototype = new THREE.Object3D(); -THREE.Light.prototype.constructor = THREE.Light; -THREE.Light.prototype.supr = THREE.Object3D.prototype; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.AmbientLight = function ( hex ) { - - THREE.Light.call( this, hex ); - -}; - -THREE.AmbientLight.prototype = new THREE.Light(); -THREE.AmbientLight.prototype.constructor = THREE.AmbientLight; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.DirectionalLight = function ( hex, intensity, distance, castShadow ) { - - THREE.Light.call( this, hex ); - - this.position = new THREE.Vector3( 0, 1, 0 ); - this.intensity = intensity || 1; - this.distance = distance || 0; - this.castShadow = castShadow !== undefined ? castShadow : false; - -}; - -THREE.DirectionalLight.prototype = new THREE.Light(); -THREE.DirectionalLight.prototype.constructor = THREE.DirectionalLight; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.PointLight = function ( hex, intensity, distance ) { - - THREE.Light.call( this, hex ); - - this.position = new THREE.Vector3(); - this.intensity = intensity || 1; - this.distance = distance || 0; - -}; - -THREE.PointLight.prototype = new THREE.Light(); -THREE.PointLight.prototype.constructor = THREE.PointLight; -/** - * @author Mikael Emtinger - */ - -THREE.LensFlare = function ( texture, size, distance, blending ) { - - THREE.Object3D.call( this ); - - this.positionScreen = new THREE.Vector3(); - this.lensFlares = []; - this.customUpdateCallback = undefined; - - if( texture !== undefined ) { - - this.add( texture, size, distance, blending ); - - } - -}; - -THREE.LensFlare.prototype = new THREE.Object3D(); -THREE.LensFlare.prototype.constructor = THREE.LensFlare; -THREE.LensFlare.prototype.supr = THREE.Object3D.prototype; - - -/* - * Add: adds another flare - */ - -THREE.LensFlare.prototype.add = function( texture, size, distance, blending ) { - - if( size === undefined ) size = -1; - if( distance === undefined ) distance = 0; - if( blending === undefined ) blending = THREE.BillboardBlending; - - distance = Math.min( distance, Math.max( 0, distance )); - - this.lensFlares.push( { texture: texture, // THREE.Texture - size: size, // size in pixels (-1 = use texture.width) - distance: distance, // distance (0-1) from light source (0=at light source) - x: 0, y: 0, z: 0, // screen position (-1 => 1) z = 0 is ontop z = 1 is back - scale: 1, // scale - rotation: 1, // rotation - opacity: 1, // opacity - blending: blending } ); // blending - -}; - - -/* - * Update lens flares update positions on all flares based on the screen position - * Set myLensFlare.customUpdateCallback to alter the flares in your project specific way. - */ - -THREE.LensFlare.prototype.updateLensFlares = function() { - - var f, fl = this.lensFlares.length; - var flare; - var vecX = -this.positionScreen.x * 2; - var vecY = -this.positionScreen.y * 2; - - - for( f = 0; f < fl; f++ ) { - - flare = this.lensFlares[ f ]; - - flare.x = this.positionScreen.x + vecX * flare.distance; - flare.y = this.positionScreen.y + vecY * flare.distance; - - flare.wantedRotation = flare.x * Math.PI * 0.25; - flare.rotation += ( flare.wantedRotation - flare.rotation ) * 0.25; - - } - -}; - - - - - - - - - - - - -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.Material = function ( parameters ) { - - this.id = THREE.MaterialCounter.value ++; - - parameters = parameters || {}; - - this.opacity = parameters.opacity !== undefined ? parameters.opacity : 1; - this.transparent = parameters.transparent !== undefined ? parameters.transparent : false; - - this.blending = parameters.blending !== undefined ? parameters.blending : THREE.NormalBlending; - this.depthTest = parameters.depthTest !== undefined ? parameters.depthTest : true; - - this.polygonOffset = parameters.polygonOffset !== undefined ? parameters.polygonOffset : false; - this.polygonOffsetFactor = parameters.polygonOffsetFactor !== undefined ? parameters.polygonOffsetFactor : 0; - this.polygonOffsetUnits = parameters.polygonOffsetUnits !== undefined ? parameters.polygonOffsetUnits : 0; - -} - -THREE.NoShading = 0; -THREE.FlatShading = 1; -THREE.SmoothShading = 2; - -THREE.NoColors = 0; -THREE.FaceColors = 1; -THREE.VertexColors = 2; - -THREE.NormalBlending = 0; -THREE.AdditiveBlending = 1; -THREE.SubtractiveBlending = 2; -THREE.MultiplyBlending = 3; -THREE.AdditiveAlphaBlending = 4; - - -THREE.MaterialCounter = { value: 0 }; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.CubeReflectionMapping = function () {}; -THREE.CubeRefractionMapping = function () {}; - -THREE.LatitudeReflectionMapping = function () {}; -THREE.LatitudeRefractionMapping = function () {}; - -THREE.SphericalReflectionMapping = function () {}; -THREE.SphericalRefractionMapping = function () {}; - -THREE.UVMapping = function () {}; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - - * blending: THREE.NormalBlending, - * depthTest: , - - * linewidth: , - * linecap: "round", - * linejoin: "round", - - * vertexColors: - * } - */ - -THREE.LineBasicMaterial = function ( parameters ) { - - THREE.Material.call( this, parameters ); - - parameters = parameters || {}; - - this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff ); - - this.linewidth = parameters.linewidth !== undefined ? parameters.linewidth : 1; - this.linecap = parameters.linecap !== undefined ? parameters.linecap : 'round'; - this.linejoin = parameters.linejoin !== undefined ? parameters.linejoin : 'round'; - - this.vertexColors = parameters.vertexColors ? parameters.vertexColors : false; - -}; - -THREE.LineBasicMaterial.prototype = new THREE.Material(); -THREE.LineBasicMaterial.prototype.constructor = THREE.LineBasicMaterial; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * shading: THREE.SmoothShading, - * blending: THREE.NormalBlending, - * depthTest: , - * - * wireframe: , - * wireframeLinewidth: , - * - * vertexColors: false / THREE.VertexColors / THREE.FaceColors, - * skinning: - * } - */ - -THREE.MeshBasicMaterial = function ( parameters ) { - - THREE.Material.call( this, parameters ); - - parameters = parameters || {}; - - this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff ); - - this.map = parameters.map !== undefined ? parameters.map : null; - - this.lightMap = parameters.lightMap !== undefined ? parameters.lightMap : null; - - this.envMap = parameters.envMap !== undefined ? parameters.envMap : null; - this.combine = parameters.combine !== undefined ? parameters.combine : THREE.MultiplyOperation; - this.reflectivity = parameters.reflectivity !== undefined ? parameters.reflectivity : 1; - this.refractionRatio = parameters.refractionRatio !== undefined ? parameters.refractionRatio : 0.98; - - // this.enableFog = parameters.enableFog ? parameters.enableFog : true; - - this.shading = parameters.shading !== undefined ? parameters.shading : THREE.SmoothShading; - - this.wireframe = parameters.wireframe !== undefined ? parameters.wireframe : false; - this.wireframeLinewidth = parameters.wireframeLinewidth !== undefined ? parameters.wireframeLinewidth : 1; - this.wireframeLinecap = parameters.wireframeLinecap !== undefined ? parameters.wireframeLinecap : 'round'; - this.wireframeLinejoin = parameters.wireframeLinejoin !== undefined ? parameters.wireframeLinejoin : 'round'; - - this.vertexColors = parameters.vertexColors !== undefined ? parameters.vertexColors : false; - - this.skinning = parameters.skinning !== undefined ? parameters.skinning : false; - this.morphTargets = parameters.morphTargets !== undefined ? parameters.morphTargets : false; - -}; - -THREE.MeshBasicMaterial.prototype = new THREE.Material(); -THREE.MeshBasicMaterial.prototype.constructor = THREE.MeshBasicMaterial; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * shading: THREE.SmoothShading, - * blending: THREE.NormalBlending, - * depthTest: , - * - * wireframe: , - * wireframeLinewidth: , - * - * vertexColors: false / THREE.VertexColors / THREE.FaceColors, - * skinning: - * } - */ - -THREE.MeshLambertMaterial = function ( parameters ) { - - THREE.Material.call( this, parameters ); - - parameters = parameters || {}; - - this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff ); - - this.map = parameters.map !== undefined ? parameters.map : null; - - this.lightMap = parameters.lightMap !== undefined ? parameters.lightMap : null; - - this.envMap = parameters.envMap !== undefined ? parameters.envMap : null; - this.combine = parameters.combine !== undefined ? parameters.combine : THREE.MultiplyOperation; - this.reflectivity = parameters.reflectivity !== undefined ? parameters.reflectivity : 1; - this.refractionRatio = parameters.refractionRatio !== undefined ? parameters.refractionRatio : 0.98; - - // this.enableFog = parameters.enableFog ? parameters.enableFog : true; - - this.shading = parameters.shading !== undefined ? parameters.shading : THREE.SmoothShading; - - this.wireframe = parameters.wireframe !== undefined ? parameters.wireframe : false; - this.wireframeLinewidth = parameters.wireframeLinewidth !== undefined ? parameters.wireframeLinewidth : 1; - this.wireframeLinecap = parameters.wireframeLinecap !== undefined ? parameters.wireframeLinecap : 'round'; - this.wireframeLinejoin = parameters.wireframeLinejoin !== undefined ? parameters.wireframeLinejoin : 'round'; - - this.vertexColors = parameters.vertexColors !== undefined ? parameters.vertexColors : false; - - this.skinning = parameters.skinning !== undefined ? parameters.skinning : false; - this.morphTargets = parameters.morphTargets !== undefined ? parameters.morphTargets : false; - -}; - -THREE.MeshLambertMaterial.prototype = new THREE.Material(); -THREE.MeshLambertMaterial.prototype.constructor = THREE.MeshLambertMaterial; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * ambient: , - * specular: , - * shininess: , - * opacity: , - * - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * shading: THREE.SmoothShading, - * blending: THREE.NormalBlending, - * depthTest: , - * - * wireframe: , - * wireframeLinewidth: , - * - * vertexColors: false / THREE.VertexColors / THREE.FaceColors, - * skinning: - * } - */ - -THREE.MeshPhongMaterial = function ( parameters ) { - - THREE.Material.call( this, parameters ); - - parameters = parameters || {}; - - this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff ); - this.ambient = parameters.ambient !== undefined ? new THREE.Color( parameters.ambient ) : new THREE.Color( 0x050505 ); - this.specular = parameters.specular !== undefined ? new THREE.Color( parameters.specular ) : new THREE.Color( 0x111111 ); - this.shininess = parameters.shininess !== undefined ? parameters.shininess : 30; - - this.map = parameters.map !== undefined ? parameters.map : null; - - this.lightMap = parameters.lightMap !== undefined ? parameters.lightMap : null; - - this.envMap = parameters.envMap !== undefined ? parameters.envMap : null; - this.combine = parameters.combine !== undefined ? parameters.combine : THREE.MultiplyOperation; - this.reflectivity = parameters.reflectivity !== undefined ? parameters.reflectivity : 1; - this.refractionRatio = parameters.refractionRatio !== undefined ? parameters.refractionRatio : 0.98; - - // this.enableFog = parameters.enableFog ? parameters.enableFog : true; - - this.shading = parameters.shading !== undefined ? parameters.shading : THREE.SmoothShading; - - this.wireframe = parameters.wireframe !== undefined ? parameters.wireframe : false; - this.wireframeLinewidth = parameters.wireframeLinewidth !== undefined ? parameters.wireframeLinewidth : 1; - this.wireframeLinecap = parameters.wireframeLinecap !== undefined ? parameters.wireframeLinecap : 'round'; - this.wireframeLinejoin = parameters.wireframeLinejoin !== undefined ? parameters.wireframeLinejoin : 'round'; - - this.vertexColors = parameters.vertexColors !== undefined ? parameters.vertexColors : false; - - this.skinning = parameters.skinning !== undefined ? parameters.skinning : false; - this.morphTargets = parameters.morphTargets !== undefined ? parameters.morphTargets : false; - -}; - -THREE.MeshPhongMaterial.prototype = new THREE.Material(); -THREE.MeshPhongMaterial.prototype.constructor = THREE.MeshPhongMaterial; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * opacity: , - - * blending: THREE.NormalBlending, - * depthTest: , - - * wireframe: , - * wireframeLinewidth: - * } - */ - -THREE.MeshDepthMaterial = function ( parameters ) { - - THREE.Material.call( this, parameters ); - - parameters = parameters || {}; - - this.shading = parameters.shading !== undefined ? parameters.shading : THREE.SmoothShading; // doesn't really apply here, normals are not used - - this.wireframe = parameters.wireframe !== undefined ? parameters.wireframe : false; - this.wireframeLinewidth = parameters.wireframeLinewidth !== undefined ? parameters.wireframeLinewidth : 1; - -}; - -THREE.MeshDepthMaterial.prototype = new THREE.Material(); -THREE.MeshDepthMaterial.prototype.constructor = THREE.MeshDepthMaterial; -/** - * @author mr.doob / http://mrdoob.com/ - * - * parameters = { - * opacity: , - - * shading: THREE.FlatShading, - * blending: THREE.NormalBlending, - * depthTest: , - - * wireframe: , - * wireframeLinewidth: - * } - */ - -THREE.MeshNormalMaterial = function ( parameters ) { - - THREE.Material.call( this, parameters ); - - parameters = parameters || {}; - - this.shading = parameters.shading ? parameters.shading : THREE.FlatShading; - - this.wireframe = parameters.wireframe ? parameters.wireframe : false; - this.wireframeLinewidth = parameters.wireframeLinewidth ? parameters.wireframeLinewidth : 1; - -}; - -THREE.MeshNormalMaterial.prototype = new THREE.Material(); -THREE.MeshNormalMaterial.prototype.constructor = THREE.MeshNormalMaterial; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.MeshFaceMaterial = function () { - -}; -/** - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * fragmentShader: , - * vertexShader: , - - * uniforms: { "parameter1": { type: "f", value: 1.0 }, "parameter2": { type: "i" value2: 2 } }, - - * shading: THREE.SmoothShading, - * blending: THREE.NormalBlending, - * depthTest: , - - * wireframe: , - * wireframeLinewidth: , - - * lights: , - * vertexColors: , - * skinning: , - * morphTargets: , - * } - */ - -THREE.MeshShaderMaterial = function ( parameters ) { - - THREE.Material.call( this, parameters ); - - parameters = parameters || {}; - - this.fragmentShader = parameters.fragmentShader !== undefined ? parameters.fragmentShader : "void main() {}"; - this.vertexShader = parameters.vertexShader !== undefined ? parameters.vertexShader : "void main() {}"; - this.uniforms = parameters.uniforms !== undefined ? parameters.uniforms : {}; - this.attributes = parameters.attributes; - - this.shading = parameters.shading !== undefined ? parameters.shading : THREE.SmoothShading; - - this.wireframe = parameters.wireframe !== undefined ? parameters.wireframe : false; - this.wireframeLinewidth = parameters.wireframeLinewidth !== undefined ? parameters.wireframeLinewidth : 1; - - this.fog = parameters.fog !== undefined ? parameters.fog : false; // set to use scene fog - this.lights = parameters.lights !== undefined ? parameters.lights : false; // set to use scene lights - this.vertexColors = parameters.vertexColors !== undefined ? parameters.vertexColors : false; // set to use "color" attribute stream - this.skinning = parameters.skinning !== undefined ? parameters.skinning : false; // set to use skinning attribute streams - this.morphTargets = parameters.morphTargets !== undefined ? parameters.morphTargets : false; // set to use morph targets - -}; - -THREE.MeshShaderMaterial.prototype = new THREE.Material(); -THREE.MeshShaderMaterial.prototype.constructor = THREE.MeshShaderMaterial; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - - * lightMap: new THREE.Texture( ), - - * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - - * shading: THREE.SmoothShading, - * blending: THREE.NormalBlending, - * depthTest: , - - * wireframe: , - * wireframeLinewidth: , - - * vertexColors: , - * skinning: - * } - */ - -THREE.ShadowVolumeDynamicMaterial = function ( parameters ) { - - THREE.Material.call( this, parameters ); - - parameters = parameters || {}; - - this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff ); - - this.map = parameters.map !== undefined ? parameters.map : null; - - this.lightMap = parameters.lightMap !== undefined ? parameters.lightMap : null; - - this.envMap = parameters.envMap !== undefined ? parameters.envMap : null; - this.combine = parameters.combine !== undefined ? parameters.combine : THREE.MultiplyOperation; - this.reflectivity = parameters.reflectivity !== undefined ? parameters.reflectivity : 1; - this.refractionRatio = parameters.refractionRatio !== undefined ? parameters.refractionRatio : 0.98; - - // this.enableFog = parameters.enableFog ? parameters.enableFog : true; - - this.shading = parameters.shading !== undefined ? parameters.shading : THREE.SmoothShading; - - this.wireframe = parameters.wireframe !== undefined ? parameters.wireframe : false; - this.wireframeLinewidth = parameters.wireframeLinewidth !== undefined ? parameters.wireframeLinewidth : 1; - this.wireframeLinecap = parameters.wireframeLinecap !== undefined ? parameters.wireframeLinecap : 'round'; - this.wireframeLinejoin = parameters.wireframeLinejoin !== undefined ? parameters.wireframeLinejoin : 'round'; - - this.vertexColors = parameters.vertexColors !== undefined ? parameters.vertexColors : false; - - this.skinning = parameters.skinning !== undefined ? parameters.skinning : false; - this.morphTargets = parameters.morphTargets !== undefined ? parameters.morphTargets : false; - -}; - -THREE.ShadowVolumeDynamicMaterial.prototype = new THREE.Material(); -THREE.ShadowVolumeDynamicMaterial.prototype.constructor = THREE.ShadowVolumeDynamicMaterial; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * map: new THREE.Texture( ), - - * size: , - - * blending: THREE.NormalBlending, - * depthTest: , - - * vertexColors: - * } - */ - -THREE.ParticleBasicMaterial = function ( parameters ) { - - THREE.Material.call( this, parameters ); - - parameters = parameters || {}; - - this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff ); - - this.map = parameters.map !== undefined ? parameters.map : null; - - this.size = parameters.size !== undefined ? parameters.size : 1; - this.sizeAttenuation = parameters.sizeAttenuation !== undefined ? parameters.sizeAttenuation : true; - - this.vertexColors = parameters.vertexColors !== undefined ? parameters.vertexColors : false; - -}; - -THREE.ParticleBasicMaterial.prototype = new THREE.Material(); -THREE.ParticleBasicMaterial.prototype.constructor = THREE.ParticleBasicMaterial; -/** - * @author mr.doob / http://mrdoob.com/ - * - * parameters = { - * color: , - * program: , - * opacity: , - * blending: THREE.NormalBlending - * } - */ - -THREE.ParticleCanvasMaterial = function ( parameters ) { - - THREE.Material.call( this, parameters ); - - parameters = parameters || {}; - - this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff ); - this.program = parameters.program !== undefined ? parameters.program : function ( context, color ) {}; - -}; - -THREE.ParticleCanvasMaterial.prototype = new THREE.Material(); -THREE.ParticleCanvasMaterial.prototype.constructor = THREE.ParticleCanvasMaterial; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.ParticleDOMMaterial = function ( domElement ) { - - THREE.Material.call( this ); - - this.domElement = domElement; - -}; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author szimek / https://github.com/szimek/ - */ - -THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter ) { - - this.image = image; - - this.mapping = mapping !== undefined ? mapping : new THREE.UVMapping(); - - this.wrapS = wrapS !== undefined ? wrapS : THREE.ClampToEdgeWrapping; - this.wrapT = wrapT !== undefined ? wrapT : THREE.ClampToEdgeWrapping; - - this.magFilter = magFilter !== undefined ? magFilter : THREE.LinearFilter; - this.minFilter = minFilter !== undefined ? minFilter : THREE.LinearMipMapLinearFilter; - - this.offset = new THREE.Vector2( 0, 0 ); - this.repeat = new THREE.Vector2( 1, 1 ); - - this.needsUpdate = false; - -}; - -THREE.Texture.prototype = { - - clone: function () { - - return new THREE.Texture( this.image, this.mapping, this.wrapS, this.wrapT, this.magFilter, this.minFilter ); - - } - -}; - -THREE.MultiplyOperation = 0; -THREE.MixOperation = 1; - -// Wrapping modes - -THREE.RepeatWrapping = 0; -THREE.ClampToEdgeWrapping = 1; -THREE.MirroredRepeatWrapping = 2; - -// Filters - -THREE.NearestFilter = 3; -THREE.NearestMipMapNearestFilter = 4; -THREE.NearestMipMapLinearFilter = 5; -THREE.LinearFilter = 6; -THREE.LinearMipMapNearestFilter = 7; -THREE.LinearMipMapLinearFilter = 8; - -// Types - -THREE.ByteType = 9; -THREE.UnsignedByteType = 10; -THREE.ShortType = 11; -THREE.UnsignedShortType = 12; -THREE.IntType = 13; -THREE.UnsignedIntType = 14; -THREE.FloatType = 15; - -// Formats - -THREE.AlphaFormat = 16; -THREE.RGBFormat = 17; -THREE.RGBAFormat = 18; -THREE.LuminanceFormat = 19; -THREE.LuminanceAlphaFormat = 20; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.Particle = function ( materials ) { - - THREE.Object3D.call( this ); - - this.materials = materials instanceof Array ? materials : [ materials ]; - -}; - -THREE.Particle.prototype = new THREE.Object3D(); -THREE.Particle.prototype.constructor = THREE.Particle; -/** - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.ParticleSystem = function ( geometry, materials ) { - - THREE.Object3D.call( this ); - - this.geometry = geometry; - this.materials = materials instanceof Array ? materials : [ materials ]; - - this.sortParticles = false; - -}; - -THREE.ParticleSystem.prototype = new THREE.Object3D(); -THREE.ParticleSystem.prototype.constructor = THREE.ParticleSystem; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.Line = function ( geometry, materials, type ) { - - THREE.Object3D.call( this ); - - this.geometry = geometry; - this.materials = materials instanceof Array ? materials : [ materials ]; - - this.type = ( type != undefined ) ? type : THREE.LineStrip; - -}; - -THREE.LineStrip = 0; -THREE.LinePieces = 1; - -THREE.Line.prototype = new THREE.Object3D(); -THREE.Line.prototype.constructor = THREE.Line; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.Mesh = function ( geometry, materials ) { - - THREE.Object3D.call( this ); - - this.geometry = geometry; - this.materials = materials && materials.length ? materials : [ materials ]; - - this.overdraw = false; // TODO: Move to material? - - - if ( this.geometry ) { - - // calc bound radius - - if( !this.geometry.boundingSphere ) { - - this.geometry.computeBoundingSphere(); - - } - - this.boundRadius = geometry.boundingSphere.radius; - - - // setup morph targets - - if( this.geometry.morphTargets.length ) { - - this.morphTargetBase = -1; - this.morphTargetForcedOrder = []; - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; - - for( var m = 0; m < this.geometry.morphTargets.length; m++ ) { - - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ this.geometry.morphTargets[ m ].name ] = m; - - } - - } - - } - -} - -THREE.Mesh.prototype = new THREE.Object3D(); -THREE.Mesh.prototype.constructor = THREE.Mesh; -THREE.Mesh.prototype.supr = THREE.Object3D.prototype; - - -/* - * Get Morph Target Index by Name - */ - -THREE.Mesh.prototype.getMorphTargetIndexByName = function( name ) { - - if ( this.morphTargetDictionary[ name ] !== undefined ) { - - return this.morphTargetDictionary[ name ]; - } - - console.log( "THREE.Mesh.getMorphTargetIndexByName: morph target " + name + " does not exist. Returning 0." ); - return 0; -} -/** - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.Bone = function( belongsToSkin ) { - - THREE.Object3D.call( this ); - - this.skin = belongsToSkin; - this.skinMatrix = new THREE.Matrix4(); - this.hasNoneBoneChildren = false; - -}; - -THREE.Bone.prototype = new THREE.Object3D(); -THREE.Bone.prototype.constructor = THREE.Bone; -THREE.Bone.prototype.supr = THREE.Object3D.prototype; - - -/* - * Update - */ - -THREE.Bone.prototype.update = function( parentSkinMatrix, forceUpdate, camera ) { - - // update local - - if ( this.matrixAutoUpdate ) { - - forceUpdate |= this.updateMatrix(); - - } - - // update skin matrix - - if ( forceUpdate || this.matrixWorldNeedsUpdate ) { - - if( parentSkinMatrix ) { - - this.skinMatrix.multiply( parentSkinMatrix, this.matrix ); - - } else { - - this.skinMatrix.copy( this.matrix ); - - } - - this.matrixWorldNeedsUpdate = false; - forceUpdate = true; - - } - - // update children - - var child, i, l = this.children.length; - - if ( this.hasNoneBoneChildren ) { - - this.matrixWorld.multiply( this.skin.matrixWorld, this.skinMatrix ); - - - for ( i = 0; i < l; i++ ) { - - child = this.children[ i ]; - - if ( ! ( child instanceof THREE.Bone ) ) { - - child.update( this.matrixWorld, true, camera ); - - } else { - - child.update( this.skinMatrix, forceUpdate, camera ); - - } - - } - - } else { - - for ( i = 0; i < l; i++ ) { - - this.children[ i ].update( this.skinMatrix, forceUpdate, camera ); - - } - - } - -}; - - -/* - * Add child - */ - -THREE.Bone.prototype.addChild = function( child ) { - - if ( this.children.indexOf( child ) === - 1 ) { - - if ( child.parent !== undefined ) { - - child.parent.removeChild( child ); - - } - - child.parent = this; - this.children.push( child ); - - if ( ! ( child instanceof THREE.Bone ) ) { - - this.hasNoneBoneChildren = true; - - } - - } - -}; - -/* - * TODO: Remove Children: see if any remaining are none-Bone - */ -/** - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.SkinnedMesh = function( geometry, materials ) { - - THREE.Mesh.call( this, geometry, materials ); - - // init bones - - this.identityMatrix = new THREE.Matrix4(); - this.bones = []; - this.boneMatrices = []; - - var b, bone, gbone, p, q, s; - - if ( this.geometry.bones !== undefined ) { - - for ( b = 0; b < this.geometry.bones.length; b++ ) { - - gbone = this.geometry.bones[ b ]; - - p = gbone.pos; - q = gbone.rotq; - s = gbone.scl; - - bone = this.addBone(); - - bone.name = gbone.name; - bone.position.set( p[0], p[1], p[2] ); - bone.quaternion.set( q[0], q[1], q[2], q[3] ); - bone.useQuaternion = true; - - if ( s !== undefined ) { - - bone.scale.set( s[0], s[1], s[2] ); - - } else { - - bone.scale.set( 1, 1, 1 ); - - } - - } - - for ( b = 0; b < this.bones.length; b++ ) { - - gbone = this.geometry.bones[ b ]; - bone = this.bones[ b ]; - - if ( gbone.parent === -1 ) { - - this.addChild( bone ); - - } else { - - this.bones[ gbone.parent ].addChild( bone ); - - } - - } - - this.boneMatrices = new Float32Array( 16 * this.bones.length ); - - this.pose(); - - } - -}; - -THREE.SkinnedMesh.prototype = new THREE.Mesh(); -THREE.SkinnedMesh.prototype.constructor = THREE.SkinnedMesh; - - -/* - * Update - */ - -THREE.SkinnedMesh.prototype.update = function ( parentMatrixWorld, forceUpdate, camera ) { - - // visible? - - if ( this.visible ) { - - // update local - - if ( this.matrixAutoUpdate ) { - - forceUpdate |= this.updateMatrix(); - - } - - - // update global - - if ( forceUpdate || this.matrixWorldNeedsUpdate ) { - - if ( parentMatrixWorld ) { - - this.matrixWorld.multiply( parentMatrixWorld, this.matrix ); - - } else { - - this.matrixWorld.copy( this.matrix ); - - } - - this.matrixWorldNeedsUpdate = false; - forceUpdate = true; - - } - - - // update children - - var child, i, l = this.children.length; - - for ( i = 0; i < l; i++ ) { - - child = this.children[ i ]; - - if ( child instanceof THREE.Bone ) { - - child.update( this.identityMatrix, false, camera ); - - } else { - - child.update( this.matrixWorld, forceUpdate, camera ); - - } - - } - - - // flatten to array - - var b, bl = this.bones.length; - ba = this.bones; - bm = this.boneMatrices; - - for ( b = 0; b < bl; b++ ) { - - ba[ b ].skinMatrix.flattenToArrayOffset( bm, b * 16 ); - - } - - } - -}; - - -/* - * Add - */ - -THREE.SkinnedMesh.prototype.addBone = function( bone ) { - - if ( bone === undefined ) { - - bone = new THREE.Bone( this ); - - } - - this.bones.push( bone ); - - return bone; - -}; - -/* - * Pose - */ - -THREE.SkinnedMesh.prototype.pose = function() { - - this.update( undefined, true ); - - var bim, bone, boneInverses = []; - - for ( var b = 0; b < this.bones.length; b++ ) { - - bone = this.bones[ b ]; - - boneInverses.push( THREE.Matrix4.makeInvert( bone.skinMatrix ) ); - - bone.skinMatrix.flattenToArrayOffset( this.boneMatrices, b * 16 ); - - } - - // project vertices to local - - if ( this.geometry.skinVerticesA === undefined ) { - - this.geometry.skinVerticesA = []; - this.geometry.skinVerticesB = []; - - var orgVertex, vertex; - - for ( var i = 0; i < this.geometry.skinIndices.length; i++ ) { - - orgVertex = this.geometry.vertices[ i ].position; - - var indexA = this.geometry.skinIndices[ i ].x; - var indexB = this.geometry.skinIndices[ i ].y; - - vertex = new THREE.Vector3( orgVertex.x, orgVertex.y, orgVertex.z ); - this.geometry.skinVerticesA.push( boneInverses[ indexA ].multiplyVector3( vertex ) ); - - vertex = new THREE.Vector3( orgVertex.x, orgVertex.y, orgVertex.z ); - this.geometry.skinVerticesB.push( boneInverses[ indexB ].multiplyVector3( vertex ) ); - - // todo: add more influences - - // normalize weights - - if ( this.geometry.skinWeights[ i ].x + this.geometry.skinWeights[ i ].y !== 1 ) { - - var len = ( 1.0 - ( this.geometry.skinWeights[ i ].x + this.geometry.skinWeights[ i ].y )) * 0.5; - this.geometry.skinWeights[ i ].x += len; - this.geometry.skinWeights[ i ].y += len; - - } - - } - - } - -}; -/** - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.Ribbon = function ( geometry, materials ) { - - THREE.Object3D.call( this ); - - this.geometry = geometry; - this.materials = materials instanceof Array ? materials : [ materials ]; - -}; - -THREE.Ribbon.prototype = new THREE.Object3D(); -THREE.Ribbon.prototype.constructor = THREE.Ribbon; -/** - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.Sound = function ( sources, radius, volume, loop ) { - - THREE.Object3D.call( this ); - - this.isLoaded = false; - this.isAddedToDOM = false; - this.isPlaying = false; - this.duration = -1; - this.radius = radius !== undefined ? Math.abs( radius ) : 100; - this.volume = Math.min( 1, Math.max( 0, volume !== undefined ? volume : 1 ) ); - - this.domElement = document.createElement( 'audio' ); - this.domElement.volume = 0; - this.domElement.pan = 0; - this.domElement.loop = loop !== undefined ? loop : true; - - // init sources - - this.sources = sources instanceof Array ? sources : [ sources ]; - - var element, source, type, s, sl = this.sources.length; - - for ( s = 0; s < sl; s++ ) { - - source = this.sources[ s ]; - source.toLowerCase(); - - if ( source.indexOf( ".mp3" ) !== -1 ) { - - type = "audio/mpeg"; - - } else if( source.indexOf( ".ogg" ) !== -1 ) { - - type = "audio/ogg"; - - } else if( source.indexOf( ".wav" ) !== -1 ) { - - type = "audio/wav"; - - } - - if ( this.domElement.canPlayType( type ) ) { - - element = document.createElement( "source" ); - element.src = this.sources[ s ]; - - this.domElement.THREESound = this; - this.domElement.appendChild( element ); - this.domElement.addEventListener( "canplay", this.onLoad, true ); - this.domElement.load(); - - break; - - } - - } - -}; - - -THREE.Sound.prototype = new THREE.Object3D(); -THREE.Sound.prototype.constructor = THREE.Sound; -THREE.Sound.prototype.supr = THREE.Object3D.prototype; - - -THREE.Sound.prototype.onLoad = function () { - - var sound = this.THREESound; - - if ( sound.isLoaded ) { - - return; - - } - - this.removeEventListener( "canplay", this.onLoad, true ); - - sound.isLoaded = true; - sound.duration = this.duration; - - if ( sound.isPlaying ) { - - sound.play(); - - } - -}; - -THREE.Sound.prototype.addToDOM = function ( parent ) { - - this.isAddedToDOM = true; - parent.appendChild( this.domElement ); - -}; - -THREE.Sound.prototype.play = function ( startTime ) { - - this.isPlaying = true; - - if ( this.isLoaded ) { - - this.domElement.play(); - - if ( startTime ) { - - this.domElement.currentTime = startTime % this.duration; - - } - - } - -}; - -THREE.Sound.prototype.pause = function () { - - this.isPlaying = false; - this.domElement.pause(); - -}; - -THREE.Sound.prototype.stop = function (){ - - this.isPlaying = false; - this.domElement.pause(); - this.domElement.currentTime = 0; - -}; - -THREE.Sound.prototype.calculateVolumeAndPan = function ( cameraRelativePosition ) { - - var distance = cameraRelativePosition.length(); - - if( distance <= this.radius ) { - - this.domElement.volume = this.volume * ( 1 - distance / this.radius ); - - } else { - - this.domElement.volume = 0; - - } - -}; - -THREE.Sound.prototype.update = function ( parentMatrixWorld, forceUpdate, camera ) { - - // update local (rotation/scale is not used) - - if ( this.matrixAutoUpdate ) { - - this.matrix.setPosition( this.position ); - forceUpdate = true; - - } - - // update global - - if ( forceUpdate || this.matrixWorldNeedsUpdate ) { - - if ( parentMatrixWorld ) { - - this.matrixWorld.multiply( parentMatrixWorld, this.matrix ); - - } else { - - this.matrixWorld.copy( this.matrix ); - - } - - this.matrixWorldNeedsUpdate = false; - forceUpdate = true; - - } - - // update children - - var i, l = this.children.length; - - for ( i = 0; i < l; i++ ) { - - this.children[ i ].update( this.matrixWorld, forceUpdate, camera ); - - } - -}; -/** - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.LOD = function() { - - THREE.Object3D.call( this ); - - this.LODs = []; - -}; - -THREE.LOD.prototype = new THREE.Object3D(); -THREE.LOD.prototype.constructor = THREE.LOD; -THREE.LOD.prototype.supr = THREE.Object3D.prototype; - -/* - * Add - */ - -THREE.LOD.prototype.add = function ( object3D, visibleAtDistance ) { - - if ( visibleAtDistance === undefined ) { - - visibleAtDistance = 0; - - } - - visibleAtDistance = Math.abs( visibleAtDistance ); - - for ( var l = 0; l < this.LODs.length; l++ ) { - - if ( visibleAtDistance < this.LODs[ l ].visibleAtDistance ) { - - break; - - } - - } - - this.LODs.splice( l, 0, { visibleAtDistance: visibleAtDistance, object3D: object3D } ); - this.addChild( object3D ); - -}; - - -/* - * Update - */ - -THREE.LOD.prototype.update = function ( parentMatrixWorld, forceUpdate, camera ) { - - // update local - - if ( this.matrixAutoUpdate ) { - - forceUpdate |= this.updateMatrix(); - - } - - // update global - - if ( forceUpdate || this.matrixWorldNeedsUpdate ) { - - if ( parentMatrixWorld ) { - - this.matrixWorld.multiply( parentMatrixWorld, this.matrix ); - - } else { - - this.matrixWorld.copy( this.matrix ); - - } - - this.matrixWorldNeedsUpdate = false; - forceUpdate = true; - - } - - - // update LODs - - if ( this.LODs.length > 1 ) { - - - var inverse = camera.matrixWorldInverse; - var radius = this.boundRadius * this.boundRadiusScale; - var distance = -( inverse.n31 * this.position.x + inverse.n32 * this.position.y + inverse.n33 * this.position.z + inverse.n34 ); - - this.LODs[ 0 ].object3D.visible = true; - - for ( var l = 1; l < this.LODs.length; l++ ) { - - if( distance >= this.LODs[ l ].visibleAtDistance ) { - - this.LODs[ l - 1 ].object3D.visible = false; - this.LODs[ l ].object3D.visible = true; - - } else { - - break; - - } - - } - - for( ; l < this.LODs.length; l++ ) { - - this.LODs[ l ].object3D.visible = false; - - } - - } - - // update children - - for ( var c = 0; c < this.children.length; c++ ) { - - this.children[ c ].update( this.matrixWorld, forceUpdate, camera ); - - } - - -}; -/** - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.ShadowVolume = function( meshOrGeometry, isStatic ) { - - if( meshOrGeometry instanceof THREE.Mesh ) { - - THREE.Mesh.call( this, meshOrGeometry.geometry, isStatic ? [ new THREE.ShadowVolumeDynamicMaterial() ] : [ new THREE.ShadowVolumeDynamicMaterial() ] ); - meshOrGeometry.addChild( this ); - - } else { - - THREE.Mesh.call( this, meshOrGeometry, isStatic ? [ new THREE.ShadowVolumeDynamicMaterial() ] : [ new THREE.ShadowVolumeDynamicMaterial() ] ); - - } - - this.calculateShadowVolumeGeometry(); - -}; - -THREE.ShadowVolume.prototype = new THREE.Mesh(); -THREE.ShadowVolume.prototype.constructor = THREE.ShadowVolume; -THREE.ShadowVolume.prototype.supr = THREE.Mesh.prototype; - - -/* - * Calculate Shadow Faces - */ - -THREE.ShadowVolume.prototype.calculateShadowVolumeGeometry = function() { - - if ( this.geometry.edges && this.geometry.edges.length ) { - - var f, fl, face, faceA, faceB, faceAIndex, faceBIndex, vertexA, vertexB; - var faceACombination, faceBCombination; - var faceAvertexAIndex, faceAvertexBIndex, faceBvertexAIndex, faceBvertexBIndex; - var e, el, edge, temp; - - var newGeometry = new THREE.Geometry(); - var vertices = newGeometry.vertices = this.geometry.vertices; - var faces = newGeometry.faces = this.geometry.faces; - var edges = newGeometry.egdes = this.geometry.edges; - var edgeFaces = newGeometry.edgeFaces = []; - - var vertexOffset = 0; - var vertexOffsetPerFace = []; - - for( f = 0, fl = faces.length; f < fl; f++ ) { - - face = faces[ f ]; - - // calculate faces vertex offset - - vertexOffsetPerFace.push( vertexOffset ); - vertexOffset += face instanceof THREE.Face3 ? 3 : 4; - - // set vertex normals to face normal - - face.vertexNormals[ 0 ] = face.normal; - face.vertexNormals[ 1 ] = face.normal; - face.vertexNormals[ 2 ] = face.normal; - - if( face instanceof THREE.Face4 ) face.vertexNormals[ 3 ] = face.normal; - - } - - - // setup edge faces - - for( e = 0, el = edges.length; e < el; e++ ) { - - edge = edges[ e ]; - - faceA = edge.faces[ 0 ]; - faceB = edge.faces[ 1 ]; - - faceAIndex = edge.faceIndices[ 0 ]; - faceBIndex = edge.faceIndices[ 1 ]; - - vertexA = edge.vertexIndices[ 0 ]; - vertexB = edge.vertexIndices[ 1 ]; - - // find combination and processed vertex index (vertices are split up by renderer) - - if( faceA.a === vertexA ) { faceACombination = "a"; faceAvertexAIndex = vertexOffsetPerFace[ faceAIndex ] + 0; } - else if( faceA.b === vertexA ) { faceACombination = "b"; faceAvertexAIndex = vertexOffsetPerFace[ faceAIndex ] + 1; } - else if( faceA.c === vertexA ) { faceACombination = "c"; faceAvertexAIndex = vertexOffsetPerFace[ faceAIndex ] + 2; } - else if( faceA.d === vertexA ) { faceACombination = "d"; faceAvertexAIndex = vertexOffsetPerFace[ faceAIndex ] + 3; } - - if( faceA.a === vertexB ) { faceACombination += "a"; faceAvertexBIndex = vertexOffsetPerFace[ faceAIndex ] + 0; } - else if( faceA.b === vertexB ) { faceACombination += "b"; faceAvertexBIndex = vertexOffsetPerFace[ faceAIndex ] + 1; } - else if( faceA.c === vertexB ) { faceACombination += "c"; faceAvertexBIndex = vertexOffsetPerFace[ faceAIndex ] + 2; } - else if( faceA.d === vertexB ) { faceACombination += "d"; faceAvertexBIndex = vertexOffsetPerFace[ faceAIndex ] + 3; } - - if( faceB.a === vertexA ) { faceBCombination = "a"; faceBvertexAIndex = vertexOffsetPerFace[ faceBIndex ] + 0; } - else if( faceB.b === vertexA ) { faceBCombination = "b"; faceBvertexAIndex = vertexOffsetPerFace[ faceBIndex ] + 1; } - else if( faceB.c === vertexA ) { faceBCombination = "c"; faceBvertexAIndex = vertexOffsetPerFace[ faceBIndex ] + 2; } - else if( faceB.d === vertexA ) { faceBCombination = "d"; faceBvertexAIndex = vertexOffsetPerFace[ faceBIndex ] + 3; } - - if( faceB.a === vertexB ) { faceBCombination += "a"; faceBvertexBIndex = vertexOffsetPerFace[ faceBIndex ] + 0; } - else if( faceB.b === vertexB ) { faceBCombination += "b"; faceBvertexBIndex = vertexOffsetPerFace[ faceBIndex ] + 1; } - else if( faceB.c === vertexB ) { faceBCombination += "c"; faceBvertexBIndex = vertexOffsetPerFace[ faceBIndex ] + 2; } - else if( faceB.d === vertexB ) { faceBCombination += "d"; faceBvertexBIndex = vertexOffsetPerFace[ faceBIndex ] + 3; } - - if( faceACombination === "ac" || - faceACombination === "ad" || - faceACombination === "ca" || - faceACombination === "da" ) { - - if( faceAvertexAIndex > faceAvertexBIndex ) { - - temp = faceAvertexAIndex; - faceAvertexAIndex = faceAvertexBIndex; - faceAvertexBIndex = temp; - - } - - } else { - - if( faceAvertexAIndex < faceAvertexBIndex ) { - - temp = faceAvertexAIndex; - faceAvertexAIndex = faceAvertexBIndex; - faceAvertexBIndex = temp; - - } - - } - - if( faceBCombination === "ac" || - faceBCombination === "ad" || - faceBCombination === "ca" || - faceBCombination === "da" ) { - - if( faceBvertexAIndex > faceBvertexBIndex ) { - - temp = faceBvertexAIndex; - faceBvertexAIndex = faceBvertexBIndex; - faceBvertexBIndex = temp; - - } - - } else { - - if( faceBvertexAIndex < faceBvertexBIndex ) { - - temp = faceBvertexAIndex; - faceBvertexAIndex = faceBvertexBIndex; - faceBvertexBIndex = temp; - - } - - } - - face = new THREE.Face4( faceAvertexAIndex, faceAvertexBIndex, faceBvertexAIndex, faceBvertexBIndex ); - face.normal.set( 1, 0, 0 ); - edgeFaces.push( face ); - - } - - this.geometry = newGeometry; - - } else { - - this.calculateShadowVolumeGeometryWithoutEdgeInfo( this.geometry ); - - } -} - - -THREE.ShadowVolume.prototype.calculateShadowVolumeGeometryWithoutEdgeInfo = function( originalGeometry ) { - - // create geometry - - this.geometry = new THREE.Geometry(); - this.geometry.boundingSphere = originalGeometry.boundingSphere; - this.geometry.edgeFaces = []; - - // copy vertices / faces from original mesh - - var vertexTypes = this.geometry.vertexTypes; - var vertices = this.geometry.vertices; - var faces = this.geometry.faces; - var edgeFaces = this.geometry.edgeFaces; - - var originalFaces = originalGeometry.faces; - var originalVertices = originalGeometry.vertices; - var fl = originalFaces.length; - - var originalFace, face, i, f, n, vertex, numVertices; - var indices = [ "a", "b", "c", "d" ]; - - - for( f = 0; f < fl; f++ ) { - - numVertices = vertices.length; - originalFace = originalFaces[ f ]; - - if ( originalFace instanceof THREE.Face4 ) { - - n = 4; - face = new THREE.Face4( numVertices, numVertices + 1, numVertices + 2, numVertices + 3 ); - - } else { - - n = 3; - face = new THREE.Face3( numVertices, numVertices + 1, numVertices + 2 ); - - } - - face.normal.copy( originalFace.normal ); - faces.push( face ); - - - for( i = 0; i < n; i++ ) { - - vertex = originalVertices[ originalFace[ indices[ i ]]]; - vertices.push( new THREE.Vertex( vertex.position.clone())); - - } - - } - - - // calculate edge faces - - var result, faceA, faceB, v, vl; - - for( var fa = 0; fa < originalFaces.length - 1; fa++ ) { - - faceA = faces[ fa ]; - - for( var fb = fa + 1; fb < originalFaces.length; fb++ ) { - - faceB = faces[ fb ]; - result = this.facesShareEdge( vertices, faceA, faceB ); - - if( result !== undefined ) { - - numVertices = vertices.length; - face = new THREE.Face4( result.indices[ 0 ], result.indices[ 3 ], result.indices[ 2 ], result.indices[ 1 ] ); - face.normal.set( 1, 0, 0 ); - edgeFaces.push( face ); - - } - - } - - } - -}; - - -THREE.ShadowVolume.prototype.facesShareEdge = function( vertices, faceA, faceB ) { - - var indicesA, - indicesB, - indexA, - indexB, - vertexA, - vertexB, - savedVertexA, - savedVertexB, - savedIndexA, - savedIndexB, - indexLetters, - a, b, - numMatches = 0, - indices = [ "a", "b", "c", "d" ]; - - if( faceA instanceof THREE.Face4 ) indicesA = 4; - else indicesA = 3; - - if( faceB instanceof THREE.Face4 ) indicesB = 4; - else indicesB = 3; - - - for( a = 0; a < indicesA; a++ ) { - - indexA = faceA[ indices[ a ] ]; - vertexA = vertices[ indexA ]; - - for( b = 0; b < indicesB; b++ ) { - - indexB = faceB[ indices[ b ] ]; - vertexB = vertices[ indexB ]; - - if( Math.abs( vertexA.position.x - vertexB.position.x ) < 0.0001 && - Math.abs( vertexA.position.y - vertexB.position.y ) < 0.0001 && - Math.abs( vertexA.position.z - vertexB.position.z ) < 0.0001 ) { - - numMatches++; - - if( numMatches === 1 ) { - - savedVertexA = vertexA; - savedVertexB = vertexB; - savedIndexA = indexA; - savedIndexB = indexB; - indexLetters = indices[ a ]; - - } - - if( numMatches === 2 ) { - - indexLetters += indices[ a ]; - - if( indexLetters === "ad" || indexLetters === "ac" ) { - - return { - - faces : [ faceA, faceB ], - vertices : [ savedVertexA, savedVertexB, vertexB, vertexA ], - indices : [ savedIndexA, savedIndexB, indexB, indexA ], - vertexTypes : [ 1, 2, 2, 1 ], - extrudable : true - - }; - - } else { - - return { - - faces : [ faceA, faceB ], - vertices : [ savedVertexA, vertexA, vertexB, savedVertexB ], - indices : [ savedIndexA, indexA, indexB, savedIndexB ], - vertexTypes : [ 1, 1, 2, 2 ], - extrudable : true - - }; - - } - - } - - } - - } - - } - - return undefined; - -}; -/** - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.Sprite = function( parameters ) { - - THREE.Object3D.call( this ); - - if( parameters.material !== undefined ) { - - this.material = parameters.material; - this.map = undefined; - this.blending = material.blending; - - } else if( parameters.map !== undefined ) { - - this.map = parameters.map instanceof THREE.Texture ? parameters.map : THREE.ImageUtils.loadTexture( parameters.map ); - this.material = undefined; - this.blending = parameters.blending !== undefined ? parameters.blending : THREE.NormalBlending; - - } - - this.useScreenCoordinates = parameters.useScreenCoordinates !== undefined ? parameters.useScreenCoordinates : true; - this.mergeWith3D = parameters.mergeWith3D !== undefined ? parameters.mergeWith3D : !this.useScreenCoordinates; - this.affectedByDistance = parameters.affectedByDistance !== undefined ? parameters.affectedByDistance : !this.useScreenCoordinates; - this.scaleByViewport = parameters.scaleByViewport !== undefined ? parameters.scaleByViewport : !this.affectedByDistance; - this.alignment = parameters.alignment instanceof THREE.Vector2 ? parameters.alignment : THREE.SpriteAlignment.center; - - this.rotation3d = this.rotation; - this.rotation = 0; - this.opacity = 1; - - this.uvOffset = new THREE.Vector2( 0, 0 ); - this.uvScale = new THREE.Vector2( 1, 1 ); - -}; - -THREE.Sprite.prototype = new THREE.Object3D(); -THREE.Sprite.prototype.constructor = THREE.Sprite; -THREE.Sprite.prototype.supr = THREE.Object3D.prototype; - - -/* - * Custom update matrix - */ - -THREE.Sprite.prototype.updateMatrix = function () { - - this.matrix.setPosition( this.position ); - - this.rotation3d.set( 0, 0, this.rotation ); - this.matrix.setRotationFromEuler( this.rotation3d ); - - if ( this.scale.x !== 1 || this.scale.y !== 1 ) { - - this.matrix.scale( this.scale ); - this.boundRadiusScale = Math.max( this.scale.x, this.scale.y ); - - } - - this.matrixWorldNeedsUpdate = true; - -}; - -/* - * Alignment - */ - -THREE.SpriteAlignment = {}; -THREE.SpriteAlignment.topLeft = new THREE.Vector2( 1, -1 ); -THREE.SpriteAlignment.topCenter = new THREE.Vector2( 0, -1 ); -THREE.SpriteAlignment.topRight = new THREE.Vector2( -1, -1 ); -THREE.SpriteAlignment.centerLeft = new THREE.Vector2( 1, 0 ); -THREE.SpriteAlignment.center = new THREE.Vector2( 0, 0 ); -THREE.SpriteAlignment.centerRight = new THREE.Vector2( -1, 0 ); -THREE.SpriteAlignment.bottomLeft = new THREE.Vector2( 1, 1 ); -THREE.SpriteAlignment.bottomCenter = new THREE.Vector2( 0, 1 ); -THREE.SpriteAlignment.bottomRight = new THREE.Vector2( -1, 1 ); -/** - * @author mr.doob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.Scene = function () { - - THREE.Object3D.call( this ); - - this.matrixAutoUpdate = false; - - this.fog = null; - - this.collisions = null; - - this.objects = []; - this.lights = []; - this.sounds = []; - - this.__objectsAdded = []; - this.__objectsRemoved = []; - -}; - -THREE.Scene.prototype = new THREE.Object3D(); -THREE.Scene.prototype.constructor = THREE.Scene; -THREE.Scene.prototype.supr = THREE.Object3D.prototype; - -THREE.Scene.prototype.addChild = function( child ) { - - this.supr.addChild.call( this, child ); - this.addChildRecurse( child ); - -} - -THREE.Scene.prototype.addChildRecurse = function( child ) { - - if ( child instanceof THREE.Light ) { - - if ( this.lights.indexOf( child ) === -1 ) { - - this.lights.push( child ); - - } - - } else if ( child instanceof THREE.Sound ) { - - if ( this.sounds.indexOf( child ) === -1 ) { - - this.sounds.push( child ); - - } - - } else if ( !( child instanceof THREE.Camera || child instanceof THREE.Bone ) ) { - - if ( this.objects.indexOf( child ) === -1 ) { - - this.objects.push( child ); - this.__objectsAdded.push( child ); - - } - - } - - for ( var c = 0; c < child.children.length; c++ ) { - - this.addChildRecurse( child.children[ c ] ); - - } - -} - - -THREE.Scene.prototype.removeChild = function( child ) { - - this.supr.removeChild.call( this, child ); - this.removeChildRecurse( child ); - -} - -THREE.Scene.prototype.removeChildRecurse = function( child ) { - - if ( child instanceof THREE.Light ) { - - var i = this.lights.indexOf( child ); - - if ( i !== -1 ) { - - this.lights.splice( i, 1 ); - - } - - } else if ( child instanceof THREE.Sound ) { - - var i = this.sounds.indexOf( child ); - - if( i !== -1 ) { - - this.sounds.splice( i, 1 ); - - } - - } else if ( !( child instanceof THREE.Camera ) ) { - - var i = this.objects.indexOf( child ); - - if( i !== -1 ) { - - this.objects.splice( i, 1 ); - this.__objectsRemoved.push( child ); - - } - - } - - for ( var c = 0; c < child.children.length; c++ ) { - - this.removeChildRecurse( child.children[ c ] ); - - } - -} - -THREE.Scene.prototype.addObject = THREE.Scene.prototype.addChild; -THREE.Scene.prototype.removeObject = THREE.Scene.prototype.removeChild; -THREE.Scene.prototype.addLight = THREE.Scene.prototype.addChild; -THREE.Scene.prototype.removeLight = THREE.Scene.prototype.removeChild; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.Fog = function ( hex, near, far ) { - - this.color = new THREE.Color( hex ); - this.near = near || 1; - this.far = far || 1000; - -}; -/** - * @author mr.doob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.FogExp2 = function ( hex, density ) { - - this.color = new THREE.Color( hex ); - this.density = ( density !== undefined ) ? density : 0.00025; - -}; -/** - * @author mr.doob / http://mrdoob.com/ - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author julianwa / https://github.com/julianwa - */ - -THREE.Projector = function() { - - var _object, _objectCount, _objectPool = [], - _vertex, _vertexCount, _vertexPool = [], - _face, _face3Count, _face3Pool = [], _face4Count, _face4Pool = [], - _line, _lineCount, _linePool = [], - _particle, _particleCount, _particlePool = [], - - _vector3 = new THREE.Vector4(), - _vector4 = new THREE.Vector4(), - _projScreenMatrix = new THREE.Matrix4(), - _projScreenObjectMatrix = new THREE.Matrix4(), - - _frustum = [ - new THREE.Vector4(), - new THREE.Vector4(), - new THREE.Vector4(), - new THREE.Vector4(), - new THREE.Vector4(), - new THREE.Vector4() - ], - - _clippedVertex1PositionScreen = new THREE.Vector4(), - _clippedVertex2PositionScreen = new THREE.Vector4(), - - _face3VertexNormals; - - - this.projectVector = function ( vector, camera ) { - - _projScreenMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse ); - _projScreenMatrix.multiplyVector3( vector ); - - return vector; - - }; - - this.unprojectVector = function ( vector, camera ) { - - _projScreenMatrix.multiply( camera.matrixWorld, THREE.Matrix4.makeInvert( camera.projectionMatrix ) ); - _projScreenMatrix.multiplyVector3( vector ); - - return vector; - - }; - - this.projectObjects = function ( scene, camera, sort ) { - - var renderList = [], - o, ol, objects, object, matrix; - - _objectCount = 0; - - objects = scene.objects; - - for ( o = 0, ol = objects.length; o < ol; o ++ ) { - - object = objects[ o ]; - - if ( !object.visible || ( object instanceof THREE.Mesh && !isInFrustum( object ) ) ) continue; - - _object = getNextObjectInPool(); - - _vector3.copy( object.position ); - _projScreenMatrix.multiplyVector3( _vector3 ); - - _object.object = object; - _object.z = _vector3.z; - - renderList.push( _object ); - - } - - sort && renderList.sort( painterSort ); - - return renderList; - - }; - - // TODO: Rename to projectElements? - - this.projectScene = function ( scene, camera, sort ) { - - var renderList = [], near = camera.near, far = camera.far, - o, ol, v, vl, f, fl, n, nl, c, cl, u, ul, objects, object, - objectMatrix, objectMatrixRotation, objectMaterials, objectOverdraw, - geometry, vertices, vertex, vertexPositionScreen, - faces, face, faceVertexNormals, normal, faceVertexUvs, uvs, - v1, v2, v3, v4; - - _face3Count = 0; - _face4Count = 0; - _lineCount = 0; - _particleCount = 0; - - camera.matrixAutoUpdate && camera.update( undefined, true ); - - scene.update( undefined, false, camera ); - - _projScreenMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse ); - computeFrustum( _projScreenMatrix ); - - objects = this.projectObjects( scene, camera, true ); - - for ( o = 0, ol = objects.length; o < ol; o++ ) { - - object = objects[ o ].object; - - if ( !object.visible ) continue; - - objectMatrix = object.matrixWorld; - objectMatrixRotation = object.matrixRotationWorld; - - objectMaterials = object.materials; - objectOverdraw = object.overdraw; - - _vertexCount = 0; - - if ( object instanceof THREE.Mesh ) { - - geometry = object.geometry; - vertices = geometry.vertices; - faces = geometry.faces; - faceVertexUvs = geometry.faceVertexUvs; - - for ( v = 0, vl = vertices.length; v < vl; v ++ ) { - - _vertex = getNextVertexInPool(); - _vertex.positionWorld.copy( vertices[ v ].position ); - - objectMatrix.multiplyVector3( _vertex.positionWorld ); - - _vertex.positionScreen.copy( _vertex.positionWorld ); - _projScreenMatrix.multiplyVector4( _vertex.positionScreen ); - - _vertex.positionScreen.x /= _vertex.positionScreen.w; - _vertex.positionScreen.y /= _vertex.positionScreen.w; - - _vertex.visible = _vertex.positionScreen.z > near && _vertex.positionScreen.z < far; - - } - - for ( f = 0, fl = faces.length; f < fl; f ++ ) { - - face = faces[ f ]; - - if ( face instanceof THREE.Face3 ) { - - v1 = _vertexPool[ face.a ]; - v2 = _vertexPool[ face.b ]; - v3 = _vertexPool[ face.c ]; - - if ( v1.visible && v2.visible && v3.visible && - ( object.doubleSided || ( object.flipSided != - ( v3.positionScreen.x - v1.positionScreen.x ) * ( v2.positionScreen.y - v1.positionScreen.y ) - - ( v3.positionScreen.y - v1.positionScreen.y ) * ( v2.positionScreen.x - v1.positionScreen.x ) < 0 ) ) ) { - - _face = getNextFace3InPool(); - - _face.v1.copy( v1 ); - _face.v2.copy( v2 ); - _face.v3.copy( v3 ); - - } else { - - continue; - - } - - } else if ( face instanceof THREE.Face4 ) { - - v1 = _vertexPool[ face.a ]; - v2 = _vertexPool[ face.b ]; - v3 = _vertexPool[ face.c ]; - v4 = _vertexPool[ face.d ]; - - if ( v1.visible && v2.visible && v3.visible && v4.visible && - ( object.doubleSided || ( object.flipSided != - ( ( v4.positionScreen.x - v1.positionScreen.x ) * ( v2.positionScreen.y - v1.positionScreen.y ) - - ( v4.positionScreen.y - v1.positionScreen.y ) * ( v2.positionScreen.x - v1.positionScreen.x ) < 0 || - ( v2.positionScreen.x - v3.positionScreen.x ) * ( v4.positionScreen.y - v3.positionScreen.y ) - - ( v2.positionScreen.y - v3.positionScreen.y ) * ( v4.positionScreen.x - v3.positionScreen.x ) < 0 ) ) ) ) { - - _face = getNextFace4InPool(); - - _face.v1.copy( v1 ); - _face.v2.copy( v2 ); - _face.v3.copy( v3 ); - _face.v4.copy( v4 ); - - } else { - - continue; - - } - - } - - _face.normalWorld.copy( face.normal ); - objectMatrixRotation.multiplyVector3( _face.normalWorld ); - - _face.centroidWorld.copy( face.centroid ); - objectMatrix.multiplyVector3( _face.centroidWorld ); - - _face.centroidScreen.copy( _face.centroidWorld ); - _projScreenMatrix.multiplyVector3( _face.centroidScreen ); - - faceVertexNormals = face.vertexNormals; - - for ( n = 0, nl = faceVertexNormals.length; n < nl; n ++ ) { - - normal = _face.vertexNormalsWorld[ n ]; - normal.copy( faceVertexNormals[ n ] ); - objectMatrixRotation.multiplyVector3( normal ); - - } - - for ( c = 0, cl = faceVertexUvs.length; c < cl; c ++ ) { - - uvs = faceVertexUvs[ c ][ f ]; - - if ( !uvs ) continue; - - for ( u = 0, ul = uvs.length; u < ul; u ++ ) { - - _face.uvs[ c ][ u ] = uvs[ u ]; - - } - - } - - _face.meshMaterials = objectMaterials; - _face.faceMaterials = face.materials; - _face.overdraw = objectOverdraw; - - _face.z = _face.centroidScreen.z; - - renderList.push( _face ); - - } - - } else if ( object instanceof THREE.Line ) { - - _projScreenObjectMatrix.multiply( _projScreenMatrix, objectMatrix ); - - vertices = object.geometry.vertices; - - v1 = getNextVertexInPool(); - v1.positionScreen.copy( vertices[ 0 ].position ); - _projScreenObjectMatrix.multiplyVector4( v1.positionScreen ); - - for ( v = 1, vl = vertices.length; v < vl; v++ ) { - - v1 = getNextVertexInPool(); - v1.positionScreen.copy( vertices[ v ].position ); - _projScreenObjectMatrix.multiplyVector4( v1.positionScreen ); - - v2 = _vertexPool[ _vertexCount - 2 ]; - - _clippedVertex1PositionScreen.copy( v1.positionScreen ); - _clippedVertex2PositionScreen.copy( v2.positionScreen ); - - if ( clipLine( _clippedVertex1PositionScreen, _clippedVertex2PositionScreen ) ) { - - // Perform the perspective divide - _clippedVertex1PositionScreen.multiplyScalar( 1 / _clippedVertex1PositionScreen.w ); - _clippedVertex2PositionScreen.multiplyScalar( 1 / _clippedVertex2PositionScreen.w ); - - _line = getNextLineInPool(); - _line.v1.positionScreen.copy( _clippedVertex1PositionScreen ); - _line.v2.positionScreen.copy( _clippedVertex2PositionScreen ); - - _line.z = Math.max( _clippedVertex1PositionScreen.z, _clippedVertex2PositionScreen.z ); - - _line.materials = object.materials; - - renderList.push( _line ); - - } - } - - } else if ( object instanceof THREE.Particle ) { - - _vector4.set( object.matrixWorld.n14, object.matrixWorld.n24, object.matrixWorld.n34, 1 ); - _projScreenMatrix.multiplyVector4( _vector4 ); - - _vector4.z /= _vector4.w; - - if ( _vector4.z > 0 && _vector4.z < 1 ) { - - _particle = getNextParticleInPool(); - _particle.x = _vector4.x / _vector4.w; - _particle.y = _vector4.y / _vector4.w; - _particle.z = _vector4.z; - - _particle.rotation = object.rotation.z; - - _particle.scale.x = object.scale.x * Math.abs( _particle.x - ( _vector4.x + camera.projectionMatrix.n11 ) / ( _vector4.w + camera.projectionMatrix.n14 ) ); - _particle.scale.y = object.scale.y * Math.abs( _particle.y - ( _vector4.y + camera.projectionMatrix.n22 ) / ( _vector4.w + camera.projectionMatrix.n24 ) ); - - _particle.materials = object.materials; - - renderList.push( _particle ); - - } - - } - - } - - sort && renderList.sort( painterSort ); - - return renderList; - - }; - - // Pools - - function getNextObjectInPool() { - - var object = _objectPool[ _objectCount ] = _objectPool[ _objectCount ] || new THREE.RenderableObject(); - - _objectCount ++; - - return object; - - } - - function getNextVertexInPool() { - - var vertex = _vertexPool[ _vertexCount ] = _vertexPool[ _vertexCount ] || new THREE.RenderableVertex(); - - _vertexCount ++; - - return vertex; - - } - - function getNextFace3InPool() { - - var face = _face3Pool[ _face3Count ] = _face3Pool[ _face3Count ] || new THREE.RenderableFace3(); - - _face3Count ++; - - return face; - - } - - function getNextFace4InPool() { - - var face = _face4Pool[ _face4Count ] = _face4Pool[ _face4Count ] || new THREE.RenderableFace4(); - - _face4Count ++; - - return face; - - } - - function getNextLineInPool() { - - var line = _linePool[ _lineCount ] = _linePool[ _lineCount ] || new THREE.RenderableLine(); - - _lineCount ++; - - return line; - - } - - function getNextParticleInPool() { - - var particle = _particlePool[ _particleCount ] = _particlePool[ _particleCount ] || new THREE.RenderableParticle(); - _particleCount ++; - return particle; - - } - - // - - function painterSort( a, b ) { - - return b.z - a.z; - - } - - function computeFrustum( m ) { - - _frustum[ 0 ].set( m.n41 - m.n11, m.n42 - m.n12, m.n43 - m.n13, m.n44 - m.n14 ); - _frustum[ 1 ].set( m.n41 + m.n11, m.n42 + m.n12, m.n43 + m.n13, m.n44 + m.n14 ); - _frustum[ 2 ].set( m.n41 + m.n21, m.n42 + m.n22, m.n43 + m.n23, m.n44 + m.n24 ); - _frustum[ 3 ].set( m.n41 - m.n21, m.n42 - m.n22, m.n43 - m.n23, m.n44 - m.n24 ); - _frustum[ 4 ].set( m.n41 - m.n31, m.n42 - m.n32, m.n43 - m.n33, m.n44 - m.n34 ); - _frustum[ 5 ].set( m.n41 + m.n31, m.n42 + m.n32, m.n43 + m.n33, m.n44 + m.n34 ); - - for ( var i = 0; i < 6; i ++ ) { - - var plane = _frustum[ i ]; - plane.divideScalar( Math.sqrt( plane.x * plane.x + plane.y * plane.y + plane.z * plane.z ) ); - - } - - } - - function isInFrustum( object ) { - - var distance, matrix = object.matrixWorld, - radius = - object.geometry.boundingSphere.radius * Math.max( object.scale.x, Math.max( object.scale.y, object.scale.z ) ); - - for ( var i = 0; i < 6; i ++ ) { - - distance = _frustum[ i ].x * matrix.n14 + _frustum[ i ].y * matrix.n24 + _frustum[ i ].z * matrix.n34 + _frustum[ i ].w; - if ( distance <= radius ) return false; - - } - - return true; - - }; - - function clipLine( s1, s2 ) { - - var alpha1 = 0, alpha2 = 1, - - // Calculate the boundary coordinate of each vertex for the near and far clip planes, - // Z = -1 and Z = +1, respectively. - bc1near = s1.z + s1.w, - bc2near = s2.z + s2.w, - bc1far = - s1.z + s1.w, - bc2far = - s2.z + s2.w; - - if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) { - - // Both vertices lie entirely within all clip planes. - return true; - - } else if ( ( bc1near < 0 && bc2near < 0) || (bc1far < 0 && bc2far < 0 ) ) { - - // Both vertices lie entirely outside one of the clip planes. - return false; - - } else { - - // The line segment spans at least one clip plane. - - if ( bc1near < 0 ) { - - // v1 lies outside the near plane, v2 inside - alpha1 = Math.max( alpha1, bc1near / ( bc1near - bc2near ) ); - - } else if ( bc2near < 0 ) { - - // v2 lies outside the near plane, v1 inside - alpha2 = Math.min( alpha2, bc1near / ( bc1near - bc2near ) ); - - } - - if ( bc1far < 0 ) { - - // v1 lies outside the far plane, v2 inside - alpha1 = Math.max( alpha1, bc1far / ( bc1far - bc2far ) ); - - } else if ( bc2far < 0 ) { - - // v2 lies outside the far plane, v2 inside - alpha2 = Math.min( alpha2, bc1far / ( bc1far - bc2far ) ); - - } - - if ( alpha2 < alpha1 ) { - - // The line segment spans two boundaries, but is outside both of them. - // (This can't happen when we're only clipping against just near/far but good - // to leave the check here for future usage if other clip planes are added.) - return false; - - } else { - - // Update the s1 and s2 vertices to match the clipped line segment. - s1.lerpSelf( s2, alpha1 ); - s2.lerpSelf( s1, 1 - alpha2 ); - - return true; - - } - - } - - } - -}; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.DOMRenderer = function () { - - THREE.Renderer.call( this ); - - var _renderList = null, - _projector = new THREE.Projector(), - _div = document.createElement( 'div' ), - _width, _height, _widthHalf, _heightHalf; - - this.domElement = _div; - - this.setSize = function ( width, height ) { - - _width = width; _height = height; - _widthHalf = _width / 2; _heightHalf = _height / 2; - - }; - - this.render = function ( scene, camera ) { - - var e, el, m, ml, element, material, dom, v1x, v1y; - - _renderList = _projector.projectScene( scene, camera ); - - for ( e = 0, el = _renderList.length; e < el; e++ ) { - - element = _renderList[ e ]; - - if ( element instanceof THREE.RenderableParticle ) { - - v1x = element.x * _widthHalf + _widthHalf; v1y = element.y * _heightHalf + _heightHalf; - - for ( m = 0, ml = element.material.length; m < ml; m++ ) { - - material = element.material[ m ]; - - if ( material instanceof THREE.ParticleDOMMaterial ) { - - dom = material.domElement; - dom.style.left = v1x + 'px'; - dom.style.top = v1y + 'px'; - - } - - } - - } - - } - - }; - -} -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.CanvasRenderer = function ( parameters ) { - - var _this = this, - _renderList = null, - _projector = new THREE.Projector(), - - parameters = parameters || {}, - - _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ), - - _canvasWidth, _canvasHeight, _canvasWidthHalf, _canvasHeightHalf, - _context = _canvas.getContext( '2d' ), - - _clearColor = new THREE.Color( 0x000000 ), - _clearOpacity = 0, - - _contextGlobalAlpha = 1, - _contextGlobalCompositeOperation = 0, - _contextStrokeStyle = null, - _contextFillStyle = null, - _contextLineWidth = null, - _contextLineCap = null, - _contextLineJoin = null, - - _v1, _v2, _v3, _v4, - _v5 = new THREE.RenderableVertex(), - _v6 = new THREE.RenderableVertex(), - - _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, - _v4x, _v4y, _v5x, _v5y, _v6x, _v6y, - - _color = new THREE.Color( 0x000000 ), - _color1 = new THREE.Color( 0x000000 ), - _color2 = new THREE.Color( 0x000000 ), - _color3 = new THREE.Color( 0x000000 ), - _color4 = new THREE.Color( 0x000000 ), - - _near, _far, - - _bitmap, _uvs, - _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, - - _clipRect = new THREE.Rectangle(), - _clearRect = new THREE.Rectangle(), - _bboxRect = new THREE.Rectangle(), - - _enableLighting = false, - _light = new THREE.Color(), - _ambientLight = new THREE.Color(), - _directionalLights = new THREE.Color(), - _pointLights = new THREE.Color(), - - _pi2 = Math.PI * 2, - _vector3 = new THREE.Vector3(), // Needed for PointLight - - _pixelMap, _pixelMapContext, _pixelMapImage, _pixelMapData, - _gradientMap, _gradientMapContext, _gradientMapQuality = 16; - - _pixelMap = document.createElement( 'canvas' ); - _pixelMap.width = _pixelMap.height = 2; - - _pixelMapContext = _pixelMap.getContext( '2d' ); - _pixelMapContext.fillStyle = 'rgba(0,0,0,1)'; - _pixelMapContext.fillRect( 0, 0, 2, 2 ); - - _pixelMapImage = _pixelMapContext.getImageData( 0, 0, 2, 2 ); - _pixelMapData = _pixelMapImage.data; - - _gradientMap = document.createElement( 'canvas' ); - _gradientMap.width = _gradientMap.height = _gradientMapQuality; - - _gradientMapContext = _gradientMap.getContext( '2d' ); - _gradientMapContext.translate( - _gradientMapQuality / 2, - _gradientMapQuality / 2 ); - _gradientMapContext.scale( _gradientMapQuality, _gradientMapQuality ); - - _gradientMapQuality --; // Fix UVs - - this.domElement = _canvas; - - this.autoClear = true; - this.sortObjects = true; - this.sortElements = true; - - this.data = { - - vertices: 0, - faces: 0 - - } - - this.setSize = function ( width, height ) { - - _canvasWidth = width; - _canvasHeight = height; - _canvasWidthHalf = _canvasWidth / 2; - _canvasHeightHalf = _canvasHeight / 2; - - _canvas.width = _canvasWidth; - _canvas.height = _canvasHeight; - - _clipRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf ); - - _contextGlobalAlpha = 1; - _contextGlobalCompositeOperation = 0; - _contextStrokeStyle = null; - _contextFillStyle = null; - _contextLineWidth = null; - _contextLineCap = null; - _contextLineJoin = null; - - }; - - this.setClearColor = function( color, opacity ) { - - _clearColor = color; - _clearOpacity = opacity; - - }; - - this.setClearColorHex = function( hex, opacity ) { - - _clearColor.setHex( hex ); - _clearOpacity = opacity; - - }; - - this.clear = function () { - - _context.setTransform( 1, 0, 0, - 1, _canvasWidthHalf, _canvasHeightHalf ); - - if ( !_clearRect.isEmpty() ) { - - _clearRect.inflate( 1 ); - _clearRect.minSelf( _clipRect ); - - if ( _clearColor.hex == 0x000000 && _clearOpacity == 0 ) { - - _context.clearRect( _clearRect.getX(), _clearRect.getY(), _clearRect.getWidth(), _clearRect.getHeight() ); - - } else { - - setBlending( THREE.NormalBlending ); - setOpacity( 1 ); - - _context.fillStyle = 'rgba(' + Math.floor( _clearColor.r * 255 ) + ',' + Math.floor( _clearColor.g * 255 ) + ',' + Math.floor( _clearColor.b * 255 ) + ',' + _clearOpacity + ')'; - _context.fillRect( _clearRect.getX(), _clearRect.getY(), _clearRect.getWidth(), _clearRect.getHeight() ); - - } - - _clearRect.empty(); - - } - - }; - - this.render = function ( scene, camera ) { - - var e, el, element, m, ml, fm, fml, material; - - this.autoClear ? this.clear() : _context.setTransform( 1, 0, 0, - 1, _canvasWidthHalf, _canvasHeightHalf ); - - _this.data.vertices = 0; - _this.data.faces = 0; - - _renderList = _projector.projectScene( scene, camera, this.sortElements ); - - /* DEBUG - _context.fillStyle = 'rgba( 0, 255, 255, 0.5 )'; - _context.fillRect( _clipRect.getX(), _clipRect.getY(), _clipRect.getWidth(), _clipRect.getHeight() ); - */ - - _enableLighting = scene.lights.length > 0; - - if ( _enableLighting ) { - - calculateLights( scene ); - - } - - for ( e = 0, el = _renderList.length; e < el; e++ ) { - - element = _renderList[ e ]; - - _bboxRect.empty(); - - if ( element instanceof THREE.RenderableParticle ) { - - _v1 = element; - _v1.x *= _canvasWidthHalf; _v1.y *= _canvasHeightHalf; - - m = 0; ml = element.materials.length; - - while( m < ml ) { - - material = element.materials[ m ++ ]; - material.opacity != 0 && renderParticle( _v1, element, material, scene ); - - } - - } else if ( element instanceof THREE.RenderableLine ) { - - _v1 = element.v1; _v2 = element.v2; - - _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf; - _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf; - - _bboxRect.addPoint( _v1.positionScreen.x, _v1.positionScreen.y ); - _bboxRect.addPoint( _v2.positionScreen.x, _v2.positionScreen.y ); - - if ( _clipRect.instersects( _bboxRect ) ) { - - m = 0; ml = element.materials.length; - - while ( m < ml ) { - - material = element.materials[ m ++ ]; - material.opacity != 0 && renderLine( _v1, _v2, element, material, scene ); - - } - - } - - - } else if ( element instanceof THREE.RenderableFace3 ) { - - _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; - - _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf; - _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf; - _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf; - - if ( element.overdraw ) { - - expand( _v1.positionScreen, _v2.positionScreen ); - expand( _v2.positionScreen, _v3.positionScreen ); - expand( _v3.positionScreen, _v1.positionScreen ); - - } - - _bboxRect.add3Points( _v1.positionScreen.x, _v1.positionScreen.y, - _v2.positionScreen.x, _v2.positionScreen.y, - _v3.positionScreen.x, _v3.positionScreen.y ); - - if ( _clipRect.instersects( _bboxRect ) ) { - - m = 0; ml = element.meshMaterials.length; - - while ( m < ml ) { - - material = element.meshMaterials[ m ++ ]; - - if ( material instanceof THREE.MeshFaceMaterial ) { - - fm = 0; fml = element.faceMaterials.length; - - while ( fm < fml ) { - - material = element.faceMaterials[ fm ++ ]; - material && material.opacity != 0 && renderFace3( _v1, _v2, _v3, 0, 1, 2, element, material, scene ); - - } - - continue; - - } - - material.opacity != 0 && renderFace3( _v1, _v2, _v3, 0, 1, 2, element, material, scene ); - - } - - } - - } else if ( element instanceof THREE.RenderableFace4 ) { - - _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; _v4 = element.v4; - - _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf; - _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf; - _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf; - _v4.positionScreen.x *= _canvasWidthHalf; _v4.positionScreen.y *= _canvasHeightHalf; - - _v5.positionScreen.copy( _v2.positionScreen ); - _v6.positionScreen.copy( _v4.positionScreen ); - - if ( element.overdraw ) { - - expand( _v1.positionScreen, _v2.positionScreen ); - expand( _v2.positionScreen, _v4.positionScreen ); - expand( _v4.positionScreen, _v1.positionScreen ); - - expand( _v3.positionScreen, _v5.positionScreen ); - expand( _v3.positionScreen, _v6.positionScreen ); - - } - - _bboxRect.addPoint( _v1.positionScreen.x, _v1.positionScreen.y ); - _bboxRect.addPoint( _v2.positionScreen.x, _v2.positionScreen.y ); - _bboxRect.addPoint( _v3.positionScreen.x, _v3.positionScreen.y ); - _bboxRect.addPoint( _v4.positionScreen.x, _v4.positionScreen.y ); - - if ( _clipRect.instersects( _bboxRect ) ) { - - m = 0; ml = element.meshMaterials.length; - - while ( m < ml ) { - - material = element.meshMaterials[ m ++ ]; - - if ( material instanceof THREE.MeshFaceMaterial ) { - - fm = 0; fml = element.faceMaterials.length; - - while ( fm < fml ) { - - material = element.faceMaterials[ fm ++ ]; - material && material.opacity != 0 && renderFace4( _v1, _v2, _v3, _v4, _v5, _v6, element, material, scene ); - - } - - continue; - - } - - material.opacity != 0 && renderFace4( _v1, _v2, _v3, _v4, _v5, _v6, element, material, scene ); - - } - - } - - } - - /* - _context.lineWidth = 1; - _context.strokeStyle = 'rgba( 0, 255, 0, 0.5 )'; - _context.strokeRect( _bboxRect.getX(), _bboxRect.getY(), _bboxRect.getWidth(), _bboxRect.getHeight() ); - */ - - _clearRect.addRectangle( _bboxRect ); - - - } - - /* DEBUG - _context.lineWidth = 1; - _context.strokeStyle = 'rgba( 255, 0, 0, 0.5 )'; - _context.strokeRect( _clearRect.getX(), _clearRect.getY(), _clearRect.getWidth(), _clearRect.getHeight() ); - */ - - _context.setTransform( 1, 0, 0, 1, 0, 0 ); - - // - - function calculateLights( scene ) { - - var l, ll, light, lightColor, - lights = scene.lights; - - _ambientLight.setRGB( 0, 0, 0 ); - _directionalLights.setRGB( 0, 0, 0 ); - _pointLights.setRGB( 0, 0, 0 ); - - for ( l = 0, ll = lights.length; l < ll; l ++ ) { - - light = lights[ l ]; - lightColor = light.color; - - if ( light instanceof THREE.AmbientLight ) { - - _ambientLight.r += lightColor.r; - _ambientLight.g += lightColor.g; - _ambientLight.b += lightColor.b; - - } else if ( light instanceof THREE.DirectionalLight ) { - - // for particles - - _directionalLights.r += lightColor.r; - _directionalLights.g += lightColor.g; - _directionalLights.b += lightColor.b; - - } else if ( light instanceof THREE.PointLight ) { - - // for particles - - _pointLights.r += lightColor.r; - _pointLights.g += lightColor.g; - _pointLights.b += lightColor.b; - - } - - } - - } - - function calculateLight( scene, position, normal, color ) { - - var l, ll, light, lightColor, - amount, lights = scene.lights; - - for ( l = 0, ll = lights.length; l < ll; l ++ ) { - - light = lights[ l ]; - lightColor = light.color; - - if ( light instanceof THREE.DirectionalLight ) { - - amount = normal.dot( light.position ); - - if ( amount <= 0 ) continue; - - amount *= light.intensity; - - color.r += lightColor.r * amount; - color.g += lightColor.g * amount; - color.b += lightColor.b * amount; - - } else if ( light instanceof THREE.PointLight ) { - - amount = normal.dot( _vector3.sub( light.position, position ).normalize() ); - - if ( amount <= 0 ) continue; - - amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( light.position ) / light.distance, 1 ); - - if ( amount == 0 ) continue; - - amount *= light.intensity; - - color.r += lightColor.r * amount; - color.g += lightColor.g * amount; - color.b += lightColor.b * amount; - - } - - } - - } - - function renderParticle ( v1, element, material, scene ) { - - setOpacity( material.opacity ); - setBlending( material.blending ); - - var width, height, scaleX, scaleY, - bitmap, bitmapWidth, bitmapHeight; - - if ( material instanceof THREE.ParticleBasicMaterial ) { - - if ( material.map ) { - - bitmap = material.map.image; - bitmapWidth = bitmap.width >> 1; - bitmapHeight = bitmap.height >> 1; - - scaleX = element.scale.x * _canvasWidthHalf; - scaleY = element.scale.y * _canvasHeightHalf; - - width = scaleX * bitmapWidth; - height = scaleY * bitmapHeight; - - // TODO: Rotations break this... - - _bboxRect.set( v1.x - width, v1.y - height, v1.x + width, v1.y + height ); - - if ( !_clipRect.instersects( _bboxRect ) ) { - - return; - - } - - _context.save(); - _context.translate( v1.x, v1.y ); - _context.rotate( - element.rotation ); - _context.scale( scaleX, - scaleY ); - - _context.translate( - bitmapWidth, - bitmapHeight ); - _context.drawImage( bitmap, 0, 0 ); - - _context.restore(); - - } - - /* DEBUG - _context.beginPath(); - _context.moveTo( v1.x - 10, v1.y ); - _context.lineTo( v1.x + 10, v1.y ); - _context.moveTo( v1.x, v1.y - 10 ); - _context.lineTo( v1.x, v1.y + 10 ); - _context.closePath(); - _context.strokeStyle = 'rgb(255,255,0)'; - _context.stroke(); - */ - - } else if ( material instanceof THREE.ParticleCanvasMaterial ) { - - width = element.scale.x * _canvasWidthHalf; - height = element.scale.y * _canvasHeightHalf; - - _bboxRect.set( v1.x - width, v1.y - height, v1.x + width, v1.y + height ); - - if ( !_clipRect.instersects( _bboxRect ) ) { - - return; - - } - - setStrokeStyle( material.color ); - setFillStyle( material.color ); - - _context.save(); - _context.translate( v1.x, v1.y ); - _context.rotate( - element.rotation ); - _context.scale( width, height ); - - material.program( _context ); - - _context.restore(); - - } - - } - - function renderLine( v1, v2, element, material, scene ) { - - setOpacity( material.opacity ); - setBlending( material.blending ); - - _context.beginPath(); - _context.moveTo( v1.positionScreen.x, v1.positionScreen.y ); - _context.lineTo( v2.positionScreen.x, v2.positionScreen.y ); - _context.closePath(); - - if ( material instanceof THREE.LineBasicMaterial ) { - - setLineWidth( material.linewidth ); - setLineCap( material.linecap ); - setLineJoin( material.linejoin ); - setStrokeStyle( material.color ); - - _context.stroke(); - _bboxRect.inflate( material.linewidth * 2 ); - - } - - } - - function renderFace3( v1, v2, v3, uv1, uv2, uv3, element, material, scene ) { - - _this.data.vertices += 3; - _this.data.faces ++; - - setOpacity( material.opacity ); - setBlending( material.blending ); - - _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y; - _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y; - _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y; - - drawTriangle( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y ); - - if ( material instanceof THREE.MeshBasicMaterial ) { - - if ( material.map/* && !material.wireframe*/ ) { - - if ( material.map.mapping instanceof THREE.UVMapping ) { - - _uvs = element.uvs[ 0 ]; - texturePath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, material.map.image, _uvs[ uv1 ].u, _uvs[ uv1 ].v, _uvs[ uv2 ].u, _uvs[ uv2 ].v, _uvs[ uv3 ].u, _uvs[ uv3 ].v ); - - } - - - } else if ( material.envMap ) { - - if ( material.envMap.mapping instanceof THREE.SphericalReflectionMapping ) { - - var cameraMatrix = camera.matrixWorldInverse; - - _vector3.copy( element.vertexNormalsWorld[ 0 ] ); - _uv1x = ( _vector3.x * cameraMatrix.n11 + _vector3.y * cameraMatrix.n12 + _vector3.z * cameraMatrix.n13 ) * 0.5 + 0.5; - _uv1y = - ( _vector3.x * cameraMatrix.n21 + _vector3.y * cameraMatrix.n22 + _vector3.z * cameraMatrix.n23 ) * 0.5 + 0.5; - - _vector3.copy( element.vertexNormalsWorld[ 1 ] ); - _uv2x = ( _vector3.x * cameraMatrix.n11 + _vector3.y * cameraMatrix.n12 + _vector3.z * cameraMatrix.n13 ) * 0.5 + 0.5; - _uv2y = - ( _vector3.x * cameraMatrix.n21 + _vector3.y * cameraMatrix.n22 + _vector3.z * cameraMatrix.n23 ) * 0.5 + 0.5; - - _vector3.copy( element.vertexNormalsWorld[ 2 ] ); - _uv3x = ( _vector3.x * cameraMatrix.n11 + _vector3.y * cameraMatrix.n12 + _vector3.z * cameraMatrix.n13 ) * 0.5 + 0.5; - _uv3y = - ( _vector3.x * cameraMatrix.n21 + _vector3.y * cameraMatrix.n22 + _vector3.z * cameraMatrix.n23 ) * 0.5 + 0.5; - - texturePath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, material.envMap.image, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y ); - - }/* else if ( material.envMap.mapping == THREE.SphericalRefractionMapping ) { - - - - }*/ - - - } else { - - material.wireframe ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( material.color ); - - } - - } else if ( material instanceof THREE.MeshLambertMaterial ) { - - if ( material.map && !material.wireframe ) { - - if ( material.map.mapping instanceof THREE.UVMapping ) { - - _uvs = element.uvs[ 0 ]; - texturePath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, material.map.image, _uvs[ uv1 ].u, _uvs[ uv1 ].v, _uvs[ uv2 ].u, _uvs[ uv2 ].v, _uvs[ uv3 ].u, _uvs[ uv3 ].v ); - - } - - setBlending( THREE.SubtractiveBlending ); - - } - - if ( _enableLighting ) { - - if ( !material.wireframe && material.shading == THREE.SmoothShading && element.vertexNormalsWorld.length == 3 ) { - - _color1.r = _color2.r = _color3.r = _ambientLight.r; - _color1.g = _color2.g = _color3.g = _ambientLight.g; - _color1.b = _color2.b = _color3.b = _ambientLight.b; - - calculateLight( scene, element.v1.positionWorld, element.vertexNormalsWorld[ 0 ], _color1 ); - calculateLight( scene, element.v2.positionWorld, element.vertexNormalsWorld[ 1 ], _color2 ); - calculateLight( scene, element.v3.positionWorld, element.vertexNormalsWorld[ 2 ], _color3 ); - - _color4.r = ( _color2.r + _color3.r ) * 0.5; - _color4.g = ( _color2.g + _color3.g ) * 0.5; - _color4.b = ( _color2.b + _color3.b ) * 0.5; - - _bitmap = getGradientTexture( _color1, _color2, _color3, _color4 ); - - texturePath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _bitmap, 0, 0, 1, 0, 0, 1 ); - - } else { - - _light.r = _ambientLight.r; - _light.g = _ambientLight.g; - _light.b = _ambientLight.b; - - calculateLight( scene, element.centroidWorld, element.normalWorld, _light ); - - _color.r = Math.max( 0, Math.min( material.color.r * _light.r, 1 ) ); - _color.g = Math.max( 0, Math.min( material.color.g * _light.g, 1 ) ); - _color.b = Math.max( 0, Math.min( material.color.b * _light.b, 1 ) ); - _color.updateHex(); - - material.wireframe ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( _color ); - - } - - } else { - - material.wireframe ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( material.color ); - - } - - } else if ( material instanceof THREE.MeshDepthMaterial ) { - - _near = camera.near; - _far = camera.far; - - _color1.r = _color1.g = _color1.b = 1 - smoothstep( v1.positionScreen.z, _near, _far ); - _color2.r = _color2.g = _color2.b = 1 - smoothstep( v2.positionScreen.z, _near, _far ); - _color3.r = _color3.g = _color3.b = 1 - smoothstep( v3.positionScreen.z, _near, _far ); - - _color4.r = ( _color2.r + _color3.r ) * 0.5; - _color4.g = ( _color2.g + _color3.g ) * 0.5; - _color4.b = ( _color2.b + _color3.b ) * 0.5; - - _bitmap = getGradientTexture( _color1, _color2, _color3, _color4 ); - - texturePath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _bitmap, 0, 0, 1, 0, 0, 1 ); - - } else if ( material instanceof THREE.MeshNormalMaterial ) { - - _color.r = normalToComponent( element.normalWorld.x ); - _color.g = normalToComponent( element.normalWorld.y ); - _color.b = normalToComponent( element.normalWorld.z ); - _color.updateHex(); - - material.wireframe ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( _color ); - - } - - } - - function renderFace4( v1, v2, v3, v4, v5, v6, element, material, scene ) { - - _this.data.vertices += 4; - _this.data.faces ++; - - setOpacity( material.opacity ); - setBlending( material.blending ); - - if ( material.map || material.envMap ) { - - // Let renderFace3() handle this - - renderFace3( v1, v2, v4, 0, 1, 3, element, material, scene ); - renderFace3( v5, v3, v6, 1, 2, 3, element, material, scene ); - - return; - - } - - _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y; - _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y; - _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y; - _v4x = v4.positionScreen.x; _v4y = v4.positionScreen.y; - _v5x = v5.positionScreen.x; _v5y = v5.positionScreen.y; - _v6x = v6.positionScreen.x; _v6y = v6.positionScreen.y; - - if ( material instanceof THREE.MeshBasicMaterial ) { - - drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y ); - - material.wireframe ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( material.color ); - - } else if ( material instanceof THREE.MeshLambertMaterial ) { - - if ( _enableLighting ) { - - if ( !material.wireframe && material.shading == THREE.SmoothShading && element.vertexNormalsWorld.length == 4 ) { - - _color1.r = _color2.r = _color3.r = _color4.r = _ambientLight.r; - _color1.g = _color2.g = _color3.g = _color4.g = _ambientLight.g; - _color1.b = _color2.b = _color3.b = _color4.b = _ambientLight.b; - - calculateLight( scene, element.v1.positionWorld, element.vertexNormalsWorld[ 0 ], _color1 ); - calculateLight( scene, element.v2.positionWorld, element.vertexNormalsWorld[ 1 ], _color2 ); - calculateLight( scene, element.v4.positionWorld, element.vertexNormalsWorld[ 3 ], _color3 ); - calculateLight( scene, element.v3.positionWorld, element.vertexNormalsWorld[ 2 ], _color4 ); - - _bitmap = getGradientTexture( _color1, _color2, _color3, _color4 ); - - // TODO: UVs are incorrect, v4->v3? - - drawTriangle( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y ); - texturePath( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y, _bitmap, 0, 0, 1, 0, 0, 1 ); - - drawTriangle( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y ); - texturePath( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y, _bitmap, 1, 0, 1, 1, 0, 1 ); - - } else { - - _light.r = _ambientLight.r; - _light.g = _ambientLight.g; - _light.b = _ambientLight.b; - - calculateLight( scene, element.centroidWorld, element.normalWorld, _light ); - - _color.r = Math.max( 0, Math.min( material.color.r * _light.r, 1 ) ); - _color.g = Math.max( 0, Math.min( material.color.g * _light.g, 1 ) ); - _color.b = Math.max( 0, Math.min( material.color.b * _light.b, 1 ) ); - _color.updateHex(); - - drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y ); - - material.wireframe ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( _color ); - - } - - } else { - - drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y ); - - material.wireframe ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( material.color ); - - } - - } else if ( material instanceof THREE.MeshNormalMaterial ) { - - _color.r = normalToComponent( element.normalWorld.x ); - _color.g = normalToComponent( element.normalWorld.y ); - _color.b = normalToComponent( element.normalWorld.z ); - _color.updateHex(); - - drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y ); - - material.wireframe ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( _color ); - - } else if ( material instanceof THREE.MeshDepthMaterial ) { - - _near = camera.near; - _far = camera.far; - - _color1.r = _color1.g = _color1.b = 1 - smoothstep( v1.positionScreen.z, _near, _far ); - _color2.r = _color2.g = _color2.b = 1 - smoothstep( v2.positionScreen.z, _near, _far ); - _color3.r = _color3.g = _color3.b = 1 - smoothstep( v4.positionScreen.z, _near, _far ); - _color4.r = _color4.g = _color4.b = 1 - smoothstep( v3.positionScreen.z, _near, _far ); - - _bitmap = getGradientTexture( _color1, _color2, _color3, _color4 ); - - // TODO: UVs are incorrect, v4->v3? - - drawTriangle( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y ); - texturePath( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y, _bitmap, 0, 0, 1, 0, 0, 1 ); - - drawTriangle( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y ); - texturePath( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y, _bitmap, 1, 0, 1, 1, 0, 1 ); - - } - - } - - // - - function drawTriangle( x0, y0, x1, y1, x2, y2 ) { - - _context.beginPath(); - _context.moveTo( x0, y0 ); - _context.lineTo( x1, y1 ); - _context.lineTo( x2, y2 ); - _context.lineTo( x0, y0 ); - _context.closePath(); - - } - - function drawQuad( x0, y0, x1, y1, x2, y2, x3, y3 ) { - - _context.beginPath(); - _context.moveTo( x0, y0 ); - _context.lineTo( x1, y1 ); - _context.lineTo( x2, y2 ); - _context.lineTo( x3, y3 ); - _context.lineTo( x0, y0 ); - _context.closePath(); - - } - - function strokePath( color, linewidth, linecap, linejoin ) { - - setLineWidth( linewidth ); - setLineCap( linecap ); - setLineJoin( linejoin ); - setStrokeStyle( color ); - - _context.stroke(); - - _bboxRect.inflate( linewidth * 2 ); - - } - - function fillPath( color ) { - - setFillStyle( color ); - _context.fill(); - - } - - function texturePath( x0, y0, x1, y1, x2, y2, bitmap, u0, v0, u1, v1, u2, v2 ) { - - /* - // http://tulrich.com/geekstuff/canvas/jsgl.js - - var m11, m12, m21, m22, dx, dy, denom, - width = bitmap.width - 1, - height = bitmap.height - 1; - - u0 *= width; v0 *= height; - u1 *= width; v1 *= height; - u2 *= width; v2 *= height; - - _context.save(); - - denom = u0 * (v2 - v1) - u1 * v2 + u2 * v1 + (u1 - u2) * v0; - - if ( denom == 0 ) return; - - m11 = - (v0 * (x2 - x1) - v1 * x2 + v2 * x1 + (v1 - v2) * x0) / denom; - m12 = (v1 * y2 + v0 * (y1 - y2) - v2 * y1 + (v2 - v1) * y0) / denom; - m21 = (u0 * (x2 - x1) - u1 * x2 + u2 * x1 + (u1 - u2) * x0) / denom; - m22 = - (u1 * y2 + u0 * (y1 - y2) - u2 * y1 + (u2 - u1) * y0) / denom; - dx = (u0 * (v2 * x1 - v1 * x2) + v0 * (u1 * x2 - u2 * x1) + (u2 * v1 - u1 * v2) * x0) / denom; - dy = (u0 * (v2 * y1 - v1 * y2) + v0 * (u1 * y2 - u2 * y1) + (u2 * v1 - u1 * v2) * y0) / denom; - - _context.transform( m11, m12, m21, m22, dx, dy ); - - _context.clip(); - _context.drawImage( bitmap, 0, 0 ); - _context.restore(); - */ - - // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120 - - var a, b, c, d, e, f, det, idet, - width = bitmap.width - 1, - height = bitmap.height - 1; - - u0 *= width; v0 *= height; - u1 *= width; v1 *= height; - u2 *= width; v2 *= height; - - x1 -= x0; y1 -= y0; - x2 -= x0; y2 -= y0; - - u1 -= u0; v1 -= v0; - u2 -= u0; v2 -= v0; - - det = u1 * v2 - u2 * v1; - - if ( det == 0 ) return; - - idet = 1 / det; - - a = ( v2 * x1 - v1 * x2 ) * idet; - b = ( v2 * y1 - v1 * y2 ) * idet; - c = ( u1 * x2 - u2 * x1 ) * idet; - d = ( u1 * y2 - u2 * y1 ) * idet; - - e = x0 - a * u0 - c * v0; - f = y0 - b * u0 - d * v0; - - _context.save(); - _context.transform( a, b, c, d, e, f ); - _context.clip(); - _context.drawImage( bitmap, 0, 0 ); - _context.restore(); - - } - - function getGradientTexture( color1, color2, color3, color4 ) { - - // http://mrdoob.com/blog/post/710 - - var c1r = ~~ ( color1.r * 255 ), c1g = ~~ ( color1.g * 255 ), c1b = ~~ ( color1.b * 255 ), - c2r = ~~ ( color2.r * 255 ), c2g = ~~ ( color2.g * 255 ), c2b = ~~ ( color2.b * 255 ), - c3r = ~~ ( color3.r * 255 ), c3g = ~~ ( color3.g * 255 ), c3b = ~~ ( color3.b * 255 ), - c4r = ~~ ( color4.r * 255 ), c4g = ~~ ( color4.g * 255 ), c4b = ~~ ( color4.b * 255 ); - - _pixelMapData[ 0 ] = c1r < 0 ? 0 : c1r > 255 ? 255 : c1r; - _pixelMapData[ 1 ] = c1g < 0 ? 0 : c1g > 255 ? 255 : c1g; - _pixelMapData[ 2 ] = c1b < 0 ? 0 : c1b > 255 ? 255 : c1b; - - _pixelMapData[ 4 ] = c2r < 0 ? 0 : c2r > 255 ? 255 : c2r; - _pixelMapData[ 5 ] = c2g < 0 ? 0 : c2g > 255 ? 255 : c2g; - _pixelMapData[ 6 ] = c2b < 0 ? 0 : c2b > 255 ? 255 : c2b; - - _pixelMapData[ 8 ] = c3r < 0 ? 0 : c3r > 255 ? 255 : c3r; - _pixelMapData[ 9 ] = c3g < 0 ? 0 : c3g > 255 ? 255 : c3g; - _pixelMapData[ 10 ] = c3b < 0 ? 0 : c3b > 255 ? 255 : c3b; - - _pixelMapData[ 12 ] = c4r < 0 ? 0 : c4r > 255 ? 255 : c4r; - _pixelMapData[ 13 ] = c4g < 0 ? 0 : c4g > 255 ? 255 : c4g; - _pixelMapData[ 14 ] = c4b < 0 ? 0 : c4b > 255 ? 255 : c4b; - - _pixelMapContext.putImageData( _pixelMapImage, 0, 0 ); - _gradientMapContext.drawImage( _pixelMap, 0, 0 ); - - return _gradientMap; - - } - - function smoothstep( value, min, max ) { - - /* - if ( value <= min ) return 0; - if ( value >= max ) return 1; - */ - - var x = ( value - min ) / ( max - min ); - return x * x * ( 3 - 2 * x ); - - } - - function normalToComponent( normal ) { - - var component = ( normal + 1 ) * 0.5; - return component < 0 ? 0 : ( component > 1 ? 1 : component ); - - } - - // Hide anti-alias gaps - - function expand( v1, v2 ) { - - var x = v2.x - v1.x, y = v2.y - v1.y, - unit = 1 / Math.sqrt( x * x + y * y ); - - x *= unit; y *= unit; - - v2.x += x; v2.y += y; - v1.x -= x; v1.y -= y; - - } - - }; - - // Context cached methods. - - function setOpacity( value ) { - - if ( _contextGlobalAlpha != value ) { - - _context.globalAlpha = _contextGlobalAlpha = value; - - } - - } - - function setBlending( value ) { - - if ( _contextGlobalCompositeOperation != value ) { - - switch ( value ) { - - case THREE.NormalBlending: - - _context.globalCompositeOperation = 'source-over'; - - break; - - case THREE.AdditiveBlending: - - _context.globalCompositeOperation = 'lighter'; - - break; - - case THREE.SubtractiveBlending: - - _context.globalCompositeOperation = 'darker'; - - break; - - } - - _contextGlobalCompositeOperation = value; - - } - - } - - function setLineWidth( value ) { - - if ( _contextLineWidth != value ) { - - _context.lineWidth = _contextLineWidth = value; - - } - - } - - function setLineCap( value ) { - - // "butt", "round", "square" - - if ( _contextLineCap != value ) { - - _context.lineCap = _contextLineCap = value; - - } - - } - - function setLineJoin( value ) { - - // "round", "bevel", "miter" - - if ( _contextLineJoin != value ) { - - _context.lineJoin = _contextLineJoin = value; - - } - - } - - function setStrokeStyle( color ) { - - if ( _contextStrokeStyle != color.hex ) { - - _contextStrokeStyle = color.hex; - _context.strokeStyle = '#' + pad( _contextStrokeStyle.toString( 16 ) ); - - } - - } - - function setFillStyle( color ) { - - if ( _contextFillStyle != color.hex ) { - - _contextFillStyle = color.hex; - _context.fillStyle = '#' + pad( _contextFillStyle.toString( 16 ) ); - - } - - } - - function pad( str ) { - - while ( str.length < 6 ) str = '0' + str; - return str; - - } - -}; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.SVGRenderer = function () { - - var _this = this, - _renderList = null, - _projector = new THREE.Projector(), - _svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), - _svgWidth, _svgHeight, _svgWidthHalf, _svgHeightHalf, - - _v1, _v2, _v3, _v4, - - _clipRect = new THREE.Rectangle(), - _bboxRect = new THREE.Rectangle(), - - _enableLighting = false, - _color = new THREE.Color( 0xffffff ), - _light = new THREE.Color( 0xffffff ), - _ambientLight = new THREE.Color( 0x000000 ), - _directionalLights = new THREE.Color( 0x000000 ), - _pointLights = new THREE.Color( 0x000000 ), - - _w, // z-buffer to w-buffer - _vector3 = new THREE.Vector3(), // Needed for PointLight - - _svgPathPool = [], _svgCirclePool = [], _svgLinePool = [], - _svgNode, _pathCount, _circleCount, _lineCount, - _quality = 1; - - this.domElement = _svg; - - this.autoClear = true; - this.sortObjects = true; - this.sortElements = true; - - this.data = { - - vertices: 0, - faces: 0 - - } - - this.setQuality = function( quality ) { - - switch(quality) { - - case "high": _quality = 1; break; - case "low": _quality = 0; break; - - } - - }; - - this.setSize = function( width, height ) { - - _svgWidth = width; _svgHeight = height; - _svgWidthHalf = _svgWidth / 2; _svgHeightHalf = _svgHeight / 2; - - _svg.setAttribute( 'viewBox', ( - _svgWidthHalf ) + ' ' + ( - _svgHeightHalf ) + ' ' + _svgWidth + ' ' + _svgHeight ); - _svg.setAttribute( 'width', _svgWidth ); - _svg.setAttribute( 'height', _svgHeight ); - - _clipRect.set( - _svgWidthHalf, - _svgHeightHalf, _svgWidthHalf, _svgHeightHalf ); - - }; - - this.clear = function () { - - while ( _svg.childNodes.length > 0 ) { - - _svg.removeChild( _svg.childNodes[ 0 ] ); - - } - - }; - - this.render = function( scene, camera ) { - - var e, el, m, ml, fm, fml, element, material; - - this.autoClear && this.clear(); - - _this.data.vertices = 0; - _this.data.faces = 0; - - _renderList = _projector.projectScene( scene, camera, this.sortElements ); - - _pathCount = 0; _circleCount = 0; _lineCount = 0; - - _enableLighting = scene.lights.length > 0; - - if ( _enableLighting ) { - - calculateLights( scene ); - - } - - for ( e = 0, el = _renderList.length; e < el; e ++ ) { - - element = _renderList[ e ]; - - _bboxRect.empty(); - - if ( element instanceof THREE.RenderableParticle ) { - - _v1 = element; - _v1.x *= _svgWidthHalf; _v1.y *= -_svgHeightHalf; - - m = 0; ml = element.materials.length; - - while ( m < ml ) { - - material = element.materials[ m ++ ]; - material && renderParticle( _v1, element, material, scene ); - - } - - } else if ( element instanceof THREE.RenderableLine ) { - - _v1 = element.v1; _v2 = element.v2; - - _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= - _svgHeightHalf; - _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf; - - _bboxRect.addPoint( _v1.positionScreen.x, _v1.positionScreen.y ); - _bboxRect.addPoint( _v2.positionScreen.x, _v2.positionScreen.y ); - - if ( !_clipRect.instersects( _bboxRect ) ) { - - continue; - - } - - m = 0; ml = element.materials.length; - - while ( m < ml ) { - - material = element.materials[ m ++ ]; - material && material.opacity != 0 && renderLine( _v1, _v2, element, material, scene ); - - } - - } else if ( element instanceof THREE.RenderableFace3 ) { - - _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; - - _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= - _svgHeightHalf; - _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf; - _v3.positionScreen.x *= _svgWidthHalf; _v3.positionScreen.y *= - _svgHeightHalf; - - _bboxRect.addPoint( _v1.positionScreen.x, _v1.positionScreen.y ); - _bboxRect.addPoint( _v2.positionScreen.x, _v2.positionScreen.y ); - _bboxRect.addPoint( _v3.positionScreen.x, _v3.positionScreen.y ); - - if ( !_clipRect.instersects( _bboxRect ) ) { - - continue; - - } - - m = 0; ml = element.meshMaterials.length; - - while ( m < ml ) { - - material = element.meshMaterials[ m ++ ]; - - if ( material instanceof THREE.MeshFaceMaterial ) { - - fm = 0; fml = element.faceMaterials.length; - - while ( fm < fml ) { - - material = element.faceMaterials[ fm ++ ]; - material && material.opacity != 0 && renderFace3( _v1, _v2, _v3, element, material, scene ); - - } - - continue; - - } - - material && material.opacity != 0 && renderFace3( _v1, _v2, _v3, element, material, scene ); - - } - - } else if ( element instanceof THREE.RenderableFace4 ) { - - _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; _v4 = element.v4; - - _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= -_svgHeightHalf; - _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= -_svgHeightHalf; - _v3.positionScreen.x *= _svgWidthHalf; _v3.positionScreen.y *= -_svgHeightHalf; - _v4.positionScreen.x *= _svgWidthHalf; _v4.positionScreen.y *= -_svgHeightHalf; - - _bboxRect.addPoint( _v1.positionScreen.x, _v1.positionScreen.y ); - _bboxRect.addPoint( _v2.positionScreen.x, _v2.positionScreen.y ); - _bboxRect.addPoint( _v3.positionScreen.x, _v3.positionScreen.y ); - _bboxRect.addPoint( _v4.positionScreen.x, _v4.positionScreen.y ); - - if ( !_clipRect.instersects( _bboxRect) ) { - - continue; - - } - - m = 0; ml = element.meshMaterials.length; - - while ( m < ml ) { - - material = element.meshMaterials[ m ++ ]; - - if ( material instanceof THREE.MeshFaceMaterial ) { - - fm = 0; fml = element.faceMaterials.length; - - while ( fm < fml ) { - - material = element.faceMaterials[ fm ++ ]; - material && material.opacity != 0 && renderFace4( _v1, _v2, _v3, _v4, element, material, scene ); - - } - - continue; - - } - - material && material.opacity != 0 && renderFace4( _v1, _v2, _v3, _v4, element, material, scene ); - - } - - } - - } - - }; - - function calculateLights( scene ) { - - var l, ll, light, lightColor, - lights = scene.lights; - - _ambientLight.setRGB( 0, 0, 0 ); - _directionalLights.setRGB( 0, 0, 0 ); - _pointLights.setRGB( 0, 0, 0 ); - - for ( l = 0, ll = lights.length; l < ll; l++ ) { - - light = lights[ l ]; - lightColor = light.color; - - if ( light instanceof THREE.AmbientLight ) { - - _ambientLight.r += lightColor.r; - _ambientLight.g += lightColor.g; - _ambientLight.b += lightColor.b; - - } else if ( light instanceof THREE.DirectionalLight ) { - - _directionalLights.r += lightColor.r; - _directionalLights.g += lightColor.g; - _directionalLights.b += lightColor.b; - - } else if ( light instanceof THREE.PointLight ) { - - _pointLights.r += lightColor.r; - _pointLights.g += lightColor.g; - _pointLights.b += lightColor.b; - - } - - } - - } - - function calculateFaceLight( scene, element, color ) { - - var l, ll, light, amount; - - for ( l = 0, ll = scene.lights.length; l < ll; l++ ) { - - light = scene.lights[ l ]; - - if ( light instanceof THREE.DirectionalLight ) { - - amount = element.normalWorld.dot( light.position ) * light.intensity; - - if ( amount > 0 ) { - - color.r += light.color.r * amount; - color.g += light.color.g * amount; - color.b += light.color.b * amount; - - } - - } else if ( light instanceof THREE.PointLight ) { - - _vector3.sub( light.position, element.centroidWorld ); - _vector3.normalize(); - - amount = element.normalWorld.dot( _vector3 ) * light.intensity; - - if ( amount > 0 ) { - - color.r += light.color.r * amount; - color.g += light.color.g * amount; - color.b += light.color.b * amount; - - } - - } - - } - - } - - function renderParticle( v1, element, material, scene ) { - - /* - _svgNode = getCircleNode( _circleCount++ ); - _svgNode.setAttribute( 'cx', v1.x ); - _svgNode.setAttribute( 'cy', v1.y ); - _svgNode.setAttribute( 'r', element.scale.x * _svgWidthHalf ); - - if ( material instanceof THREE.ParticleCircleMaterial ) { - - if ( _enableLighting ) { - - _light.r = _ambientLight.r + _directionalLights.r + _pointLights.r; - _light.g = _ambientLight.g + _directionalLights.g + _pointLights.g; - _light.b = _ambientLight.b + _directionalLights.b + _pointLights.b; - - _color.r = material.color.r * _light.r; - _color.g = material.color.g * _light.g; - _color.b = material.color.b * _light.b; - - _color.updateStyleString(); - - } else { - - _color = material.color; - - } - - _svgNode.setAttribute( 'style', 'fill: ' + _color.__styleString ); - - } - - _svg.appendChild( _svgNode ); - */ - - } - - function renderLine ( v1, v2, element, material, scene ) { - - _svgNode = getLineNode( _lineCount ++ ); - - _svgNode.setAttribute( 'x1', v1.positionScreen.x ); - _svgNode.setAttribute( 'y1', v1.positionScreen.y ); - _svgNode.setAttribute( 'x2', v2.positionScreen.x ); - _svgNode.setAttribute( 'y2', v2.positionScreen.y ); - - if ( material instanceof THREE.LineBasicMaterial ) { - - _svgNode.setAttribute( 'style', 'fill: none; stroke: #' + '#' + pad( material.color.hex.toString( 16 ) ) + '; stroke-width: ' + material.linewidth + '; stroke-opacity: ' + material.opacity + '; stroke-linecap: ' + material.linecap + '; stroke-linejoin: ' + material.linejoin ); - - _svg.appendChild( _svgNode ); - - } - - } - - function renderFace3( v1, v2, v3, element, material, scene ) { - - _this.data.vertices += 3; - _this.data.faces ++; - - _svgNode = getPathNode( _pathCount ++ ); - _svgNode.setAttribute( 'd', 'M ' + v1.positionScreen.x + ' ' + v1.positionScreen.y + ' L ' + v2.positionScreen.x + ' ' + v2.positionScreen.y + ' L ' + v3.positionScreen.x + ',' + v3.positionScreen.y + 'z' ); - - if ( material instanceof THREE.MeshBasicMaterial ) { - - _color.hex = material.color.hex; - - } else if ( material instanceof THREE.MeshLambertMaterial ) { - - if ( _enableLighting ) { - - _light.r = _ambientLight.r; - _light.g = _ambientLight.g; - _light.b = _ambientLight.b; - - calculateFaceLight( scene, element, _light ); - - _color.r = Math.max( 0, Math.min( material.color.r * _light.r, 1 ) ); - _color.g = Math.max( 0, Math.min( material.color.g * _light.g, 1 ) ); - _color.b = Math.max( 0, Math.min( material.color.b * _light.b, 1 ) ); - - _color.updateHex(); - - } else { - - _color.hex = material.color.hex; - - } - - } else if ( material instanceof THREE.MeshDepthMaterial ) { - - _w = 1 - ( material.__2near / (material.__farPlusNear - element.z * material.__farMinusNear) ); - _color.setRGB( _w, _w, _w ); - - } else if ( material instanceof THREE.MeshNormalMaterial ) { - - _color.setRGB( normalToComponent( element.normalWorld.x ), normalToComponent( element.normalWorld.y ), normalToComponent( element.normalWorld.z ) ); - - } - - if ( material.wireframe ) { - - _svgNode.setAttribute( 'style', 'fill: none; stroke: #' + pad( _color.hex.toString( 16 ) ) + '; stroke-width: ' + material.wireframeLinewidth + '; stroke-opacity: ' + material.opacity + '; stroke-linecap: ' + material.wireframeLinecap + '; stroke-linejoin: ' + material.wireframeLinejoin ); - - } else { - - _svgNode.setAttribute( 'style', 'fill: #' + pad( _color.hex.toString( 16 ) ) + '; fill-opacity: ' + material.opacity ); - - } - - _svg.appendChild( _svgNode ); - - } - - function renderFace4( v1, v2, v3, v4, element, material, scene ) { - - _this.data.vertices += 4; - _this.data.faces ++; - - _svgNode = getPathNode( _pathCount ++ ); - _svgNode.setAttribute( 'd', 'M ' + v1.positionScreen.x + ' ' + v1.positionScreen.y + ' L ' + v2.positionScreen.x + ' ' + v2.positionScreen.y + ' L ' + v3.positionScreen.x + ',' + v3.positionScreen.y + ' L ' + v4.positionScreen.x + ',' + v4.positionScreen.y + 'z' ); - - if ( material instanceof THREE.MeshBasicMaterial ) { - - _color.hex = material.color.hex; - - } else if ( material instanceof THREE.MeshLambertMaterial ) { - - if ( _enableLighting ) { - - _light.r = _ambientLight.r; - _light.g = _ambientLight.g; - _light.b = _ambientLight.b; - - calculateFaceLight( scene, element, _light ); - - _color.r = Math.max( 0, Math.min( material.color.r * _light.r, 1 ) ); - _color.g = Math.max( 0, Math.min( material.color.g * _light.g, 1 ) ); - _color.b = Math.max( 0, Math.min( material.color.b * _light.b, 1 ) ); - - _color.updateHex(); - - } else { - - _color.hex = material.color.hex; - - } - - } else if ( material instanceof THREE.MeshDepthMaterial ) { - - _w = 1 - ( material.__2near / (material.__farPlusNear - element.z * material.__farMinusNear) ); - _color.setRGB( _w, _w, _w ); - - } else if ( material instanceof THREE.MeshNormalMaterial ) { - - _color.setRGB( normalToComponent( element.normalWorld.x ), normalToComponent( element.normalWorld.y ), normalToComponent( element.normalWorld.z ) ); - - } - - if ( material.wireframe ) { - - _svgNode.setAttribute( 'style', 'fill: none; stroke: #' + pad( _color.hex.toString( 16 ) ) + '; stroke-width: ' + material.wireframeLinewidth + '; stroke-opacity: ' + material.opacity + '; stroke-linecap: ' + material.wireframeLinecap + '; stroke-linejoin: ' + material.wireframeLinejoin ); - - } else { - - _svgNode.setAttribute( 'style', 'fill: #' + pad( _color.hex.toString( 16 ) ) + '; fill-opacity: ' + material.opacity ); - - } - - _svg.appendChild( _svgNode ); - - } - - function getLineNode( id ) { - - if ( _svgLinePool[ id ] == null ) { - - _svgLinePool[ id ] = document.createElementNS( 'http://www.w3.org/2000/svg', 'line' ); - - if ( _quality == 0 ) { - - _svgLinePool[ id ].setAttribute( 'shape-rendering', 'crispEdges' ); //optimizeSpeed - - } - - return _svgLinePool[ id ]; - - } - - return _svgLinePool[ id ]; - - } - - function getPathNode( id ) { - - if ( _svgPathPool[ id ] == null ) { - - _svgPathPool[ id ] = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ); - - if ( _quality == 0 ) { - - _svgPathPool[ id ].setAttribute( 'shape-rendering', 'crispEdges' ); //optimizeSpeed - - } - - return _svgPathPool[ id ]; - - } - - return _svgPathPool[ id ]; - - } - - function getCircleNode( id ) { - - if ( _svgCirclePool[id] == null ) { - - _svgCirclePool[ id ] = document.createElementNS( 'http://www.w3.org/2000/svg', 'circle' ); - - if ( _quality == 0 ) { - - _svgCirclePool[id].setAttribute( 'shape-rendering', 'crispEdges' ); //optimizeSpeed - - } - - return _svgCirclePool[ id ]; - - } - - return _svgCirclePool[ id ]; - - } - - function normalToComponent( normal ) { - - var component = ( normal + 1 ) * 0.5; - return component < 0 ? 0 : ( component > 1 ? 1 : component ); - - } - - function pad( str ) { - - while ( str.length < 6 ) str = '0' + str; - return str; - - } - -}; -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.ShaderChunk = { - - - // FOG - - fog_pars_fragment: [ - - "#ifdef USE_FOG", - - "uniform vec3 fogColor;", - - "#ifdef FOG_EXP2", - "uniform float fogDensity;", - "#else", - "uniform float fogNear;", - "uniform float fogFar;", - "#endif", - - "#endif" - - ].join("\n"), - - fog_fragment: [ - - "#ifdef USE_FOG", - - "float depth = gl_FragCoord.z / gl_FragCoord.w;", - - "#ifdef FOG_EXP2", - "const float LOG2 = 1.442695;", - "float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );", - "fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );", - "#else", - "float fogFactor = smoothstep( fogNear, fogFar, depth );", - "#endif", - - "gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );", - - "#endif" - - ].join("\n"), - - // ENVIRONMENT MAP - - envmap_pars_fragment: [ - - "#ifdef USE_ENVMAP", - - "varying vec3 vReflect;", - "uniform float reflectivity;", - "uniform samplerCube envMap;", - "uniform int combine;", - - "#endif" - - ].join("\n"), - - envmap_fragment: [ - - "#ifdef USE_ENVMAP", - - "vec4 cubeColor = textureCube( envMap, vec3( -vReflect.x, vReflect.yz ) );", - - "if ( combine == 1 ) {", - - //"gl_FragColor = mix( gl_FragColor, cubeColor, reflectivity );", - "gl_FragColor = vec4( mix( gl_FragColor.xyz, cubeColor.xyz, reflectivity ), opacity );", - - "} else {", - - "gl_FragColor = gl_FragColor * cubeColor;", - - "}", - - "#endif" - - ].join("\n"), - - envmap_pars_vertex: [ - - "#ifdef USE_ENVMAP", - - "varying vec3 vReflect;", - "uniform float refractionRatio;", - "uniform bool useRefract;", - - "#endif" - - ].join("\n"), - - envmap_vertex : [ - - "#ifdef USE_ENVMAP", - - "vec4 mPosition = objectMatrix * vec4( position, 1.0 );", - "vec3 nWorld = mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal;", - - "if ( useRefract ) {", - - "vReflect = refract( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ), refractionRatio );", - - "} else {", - - "vReflect = reflect( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ) );", - - "}", - - "#endif" - - ].join("\n"), - - // COLOR MAP (particles) - - map_particle_pars_fragment: [ - - "#ifdef USE_MAP", - - "uniform sampler2D map;", - - "#endif" - - ].join("\n"), - - - map_particle_fragment: [ - - "#ifdef USE_MAP", - - "gl_FragColor = gl_FragColor * texture2D( map, gl_PointCoord );", - - "#endif" - - ].join("\n"), - - // COLOR MAP (triangles) - - map_pars_fragment: [ - - "#ifdef USE_MAP", - - "varying vec2 vUv;", - "uniform sampler2D map;", - - "#endif" - - ].join("\n"), - - map_pars_vertex: [ - - "#ifdef USE_MAP", - - "varying vec2 vUv;", - "uniform vec4 offsetRepeat;", - - "#endif" - - ].join("\n"), - - map_fragment: [ - - "#ifdef USE_MAP", - - "gl_FragColor = gl_FragColor * texture2D( map, vUv );", - - "#endif" - - ].join("\n"), - - map_vertex: [ - - "#ifdef USE_MAP", - - "vUv = uv * offsetRepeat.zw + offsetRepeat.xy;", - - "#endif" - - ].join("\n"), - - // LIGHT MAP - - lightmap_pars_fragment: [ - - "#ifdef USE_LIGHTMAP", - - "varying vec2 vUv2;", - "uniform sampler2D lightMap;", - - "#endif" - - ].join("\n"), - - lightmap_pars_vertex: [ - - "#ifdef USE_LIGHTMAP", - - "varying vec2 vUv2;", - - "#endif" - - ].join("\n"), - - lightmap_fragment: [ - - "#ifdef USE_LIGHTMAP", - - "gl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );", - - "#endif" - - ].join("\n"), - - lightmap_vertex: [ - - "#ifdef USE_LIGHTMAP", - - "vUv2 = uv2;", - - "#endif" - - ].join("\n"), - - lights_pars_vertex: [ - - "uniform bool enableLighting;", - "uniform vec3 ambientLightColor;", - - "#if MAX_DIR_LIGHTS > 0", - - "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];", - "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];", - - "#endif", - - "#if MAX_POINT_LIGHTS > 0", - - "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];", - "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];", - "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];", - - "#ifdef PHONG", - "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];", - "#endif", - - "#endif" - - ].join("\n"), - - // LIGHTS - - lights_vertex: [ - - "if ( !enableLighting ) {", - - "vLightWeighting = vec3( 1.0 );", - - "} else {", - - "vLightWeighting = ambientLightColor;", - - "#if MAX_DIR_LIGHTS > 0", - - "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {", - - "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );", - "float directionalLightWeighting = max( dot( transformedNormal, normalize( lDirection.xyz ) ), 0.0 );", - "vLightWeighting += directionalLightColor[ i ] * directionalLightWeighting;", - - "}", - - "#endif", - - "#if MAX_POINT_LIGHTS > 0", - - "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {", - - "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );", - - "vec3 lVector = lPosition.xyz - mvPosition.xyz;", - - "float lDistance = 1.0;", - - "if ( pointLightDistance[ i ] > 0.0 )", - "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );", - - "lVector = normalize( lVector );", - - "float pointLightWeighting = max( dot( transformedNormal, lVector ), 0.0 );", - "vLightWeighting += pointLightColor[ i ] * pointLightWeighting * lDistance;", - - "#ifdef PHONG", - "vPointLight[ i ] = vec4( lVector, lDistance );", - "#endif", - - "}", - - "#endif", - - "}" - - ].join("\n"), - - lights_pars_fragment: [ - - "#if MAX_DIR_LIGHTS > 0", - "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];", - "#endif", - - "#if MAX_POINT_LIGHTS > 0", - "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];", - "#endif", - - "varying vec3 vViewPosition;", - "varying vec3 vNormal;" - - ].join("\n"), - - lights_fragment: [ - - "vec3 normal = normalize( vNormal );", - "vec3 viewPosition = normalize( vViewPosition );", - - "vec4 mColor = vec4( diffuse, opacity );", - "vec4 mSpecular = vec4( specular, opacity );", - - "#if MAX_POINT_LIGHTS > 0", - - "vec4 pointDiffuse = vec4( 0.0 );", - "vec4 pointSpecular = vec4( 0.0 );", - - "for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {", - - "vec3 pointVector = normalize( vPointLight[ i ].xyz );", - "vec3 pointHalfVector = normalize( vPointLight[ i ].xyz + vViewPosition );", - "float pointDistance = vPointLight[ i ].w;", - - "float pointDotNormalHalf = dot( normal, pointHalfVector );", - "float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );", - - "float pointSpecularWeight = 0.0;", - - "if ( pointDotNormalHalf >= 0.0 )", - "pointSpecularWeight = pow( pointDotNormalHalf, shininess );", - - "pointDiffuse += mColor * pointDiffuseWeight * pointDistance;", - "pointSpecular += mSpecular * pointSpecularWeight * pointDistance;", - - "}", - - "#endif", - - "#if MAX_DIR_LIGHTS > 0", - - "vec4 dirDiffuse = vec4( 0.0 );", - "vec4 dirSpecular = vec4( 0.0 );" , - - "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {", - - "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );", - - "vec3 dirVector = normalize( lDirection.xyz );", - "vec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );", - - "float dirDotNormalHalf = dot( normal, dirHalfVector );", - - "float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );", - - "float dirSpecularWeight = 0.0;", - "if ( dirDotNormalHalf >= 0.0 )", - "dirSpecularWeight = pow( dirDotNormalHalf, shininess );", - - "dirDiffuse += mColor * dirDiffuseWeight;", - "dirSpecular += mSpecular * dirSpecularWeight;", - - "}", - - "#endif", - - "vec4 totalLight = vec4( ambient, opacity );", - - "#if MAX_DIR_LIGHTS > 0", - "totalLight += dirDiffuse + dirSpecular;", - "#endif", - - "#if MAX_POINT_LIGHTS > 0", - "totalLight += pointDiffuse + pointSpecular;", - "#endif", - - "gl_FragColor = gl_FragColor * totalLight;" - - ].join("\n"), - - // VERTEX COLORS - - color_pars_fragment: [ - - "#ifdef USE_COLOR", - - "varying vec3 vColor;", - - "#endif" - - ].join("\n"), - - - color_fragment: [ - - "#ifdef USE_COLOR", - - "gl_FragColor = gl_FragColor * vec4( vColor, opacity );", - - "#endif" - - ].join("\n"), - - color_pars_vertex: [ - - "#ifdef USE_COLOR", - - "varying vec3 vColor;", - - "#endif" - - ].join("\n"), - - - color_vertex: [ - - "#ifdef USE_COLOR", - - "vColor = color;", - - "#endif" - - ].join("\n"), - - // skinning - - skinning_pars_vertex: [ - - "#ifdef USE_SKINNING", - - "uniform mat4 boneGlobalMatrices[ MAX_BONES ];", - - "#endif" - - ].join("\n"), - - skinning_vertex: [ - - "#ifdef USE_SKINNING", - - "gl_Position = ( boneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;", - "gl_Position += ( boneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;", - - // this doesn't work, no idea why - //"gl_Position = projectionMatrix * cameraInverseMatrix * objectMatrix * gl_Position;", - - "gl_Position = projectionMatrix * viewMatrix * objectMatrix * gl_Position;", - - "#endif" - - ].join("\n"), - - // morphing - - morphtarget_pars_vertex: [ - - "#ifdef USE_MORPHTARGETS", - - "uniform float morphTargetInfluences[ 8 ];", - - "#endif" - - ].join("\n"), - - morphtarget_vertex: [ - - "#ifdef USE_MORPHTARGETS", - - "vec3 morphed = vec3( 0.0, 0.0, 0.0 );", - "morphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];", - "morphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];", - "morphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];", - "morphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];", - "morphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];", - "morphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];", - "morphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];", - "morphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];", - "morphed += position;", - - "gl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );", - - "#endif" - - ].join("\n"), - - default_vertex : [ - - "#ifndef USE_MORPHTARGETS", - "#ifndef USE_SKINNING", - - "gl_Position = projectionMatrix * mvPosition;", - - "#endif", - "#endif" - - ].join("\n") - -}; - -THREE.UniformsUtils = { - - merge: function ( uniforms ) { - - var u, p, tmp, merged = {}; - - for ( u = 0; u < uniforms.length; u++ ) { - - tmp = this.clone( uniforms[ u ] ); - - for ( p in tmp ) { - - merged[ p ] = tmp[ p ]; - - } - - } - - return merged; - - }, - - clone: function ( uniforms_src ) { - - var u, p, parameter, parameter_src, uniforms_dst = {}; - - for ( u in uniforms_src ) { - - uniforms_dst[ u ] = {}; - - for ( p in uniforms_src[ u ] ) { - - parameter_src = uniforms_src[ u ][ p ]; - - if ( parameter_src instanceof THREE.Color || - parameter_src instanceof THREE.Vector3 || - parameter_src instanceof THREE.Texture ) { - - uniforms_dst[ u ][ p ] = parameter_src.clone(); - - } else { - - uniforms_dst[ u ][ p ] = parameter_src; - - } - - } - - } - - return uniforms_dst; - - } - -}; - -THREE.UniformsLib = { - - common: { - - "diffuse" : { type: "c", value: new THREE.Color( 0xeeeeee ) }, - "opacity" : { type: "f", value: 1.0 }, - - "map" : { type: "t", value: 0, texture: null }, - "offsetRepeat" : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) }, - - "lightMap" : { type: "t", value: 2, texture: null }, - - "envMap" : { type: "t", value: 1, texture: null }, - "useRefract" : { type: "i", value: 0 }, - "reflectivity" : { type: "f", value: 1.0 }, - "refractionRatio" : { type: "f", value: 0.98 }, - "combine" : { type: "i", value: 0 }, - - "fogDensity" : { type: "f", value: 0.00025 }, - "fogNear" : { type: "f", value: 1 }, - "fogFar" : { type: "f", value: 2000 }, - "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) }, - - "morphTargetInfluences" : { type: "f", value: 0 } - - }, - - lights: { - - "enableLighting" : { type: "i", value: 1 }, - "ambientLightColor" : { type: "fv", value: [] }, - "directionalLightDirection" : { type: "fv", value: [] }, - "directionalLightColor" : { type: "fv", value: [] }, - "pointLightColor" : { type: "fv", value: [] }, - "pointLightPosition" : { type: "fv", value: [] }, - "pointLightDistance" : { type: "fv1", value: [] } - - }, - - particle: { - - "psColor" : { type: "c", value: new THREE.Color( 0xeeeeee ) }, - "opacity" : { type: "f", value: 1.0 }, - "size" : { type: "f", value: 1.0 }, - "scale" : { type: "f", value: 1.0 }, - "map" : { type: "t", value: 0, texture: null }, - - "fogDensity" : { type: "f", value: 0.00025 }, - "fogNear" : { type: "f", value: 1 }, - "fogFar" : { type: "f", value: 2000 }, - "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) } - - } - -}; - -THREE.ShaderLib = { - - 'lensFlareVertexTexture': { - - vertexShader: [ - - "uniform vec3 screenPosition;", - "uniform vec2 scale;", - "uniform float rotation;", - "uniform int renderType;", - - "uniform sampler2D occlusionMap;", - - "attribute vec2 position;", - "attribute vec2 UV;", - "varying vec2 vUV;", - "varying float vVisibility;", - - "void main(void)", - "{", - "vUV = UV;", - - "vec2 pos = position;", - - "if( renderType == 2 ) {", - - "vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 )) +", - "texture2D( occlusionMap, vec2( 0.5, 0.1 )) +", - "texture2D( occlusionMap, vec2( 0.9, 0.1 )) +", - "texture2D( occlusionMap, vec2( 0.9, 0.5 )) +", - "texture2D( occlusionMap, vec2( 0.9, 0.9 )) +", - "texture2D( occlusionMap, vec2( 0.5, 0.9 )) +", - "texture2D( occlusionMap, vec2( 0.1, 0.9 )) +", - "texture2D( occlusionMap, vec2( 0.1, 0.5 )) +", - "texture2D( occlusionMap, vec2( 0.5, 0.5 ));", - - "vVisibility = ( visibility.r / 9.0 ) *", - "( 1.0 - visibility.g / 9.0 ) *", - "( visibility.b / 9.0 ) *", - "( 1.0 - visibility.a / 9.0 );", - - "pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;", - "pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;", - "}", - - "gl_Position = vec4(( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );", - "}" - - ].join( "\n" ), - - fragmentShader: [ - - "#ifdef GL_ES", - "precision highp float;", - "#endif", - - "uniform sampler2D map;", - "uniform float opacity;", - "uniform int renderType;", - - "varying vec2 vUV;", - "varying float vVisibility;", - - "void main( void )", - "{", - // pink square - - "if( renderType == 0 ) {", - - "gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );", - - // restore - - "} else if( renderType == 1 ) {", - - "gl_FragColor = texture2D( map, vUV );", - - // flare - - "} else {", - - "vec4 color = texture2D( map, vUV );", - "color.a *= opacity * vVisibility;", - "gl_FragColor = color;", - "}", - "}" - ].join( "\n" ) - - }, - - - 'lensFlare': { - - vertexShader: [ - - "uniform vec3 screenPosition;", - "uniform vec2 scale;", - "uniform float rotation;", - "uniform int renderType;", - - "attribute vec2 position;", - "attribute vec2 UV;", - - "varying vec2 vUV;", - - "void main(void)", - "{", - "vUV = UV;", - - "vec2 pos = position;", - - "if( renderType == 2 ) {", - - "pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;", - "pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;", - "}", - - "gl_Position = vec4(( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );", - "}" - - ].join( "\n" ), - - fragmentShader: [ - - "#ifdef GL_ES", - "precision highp float;", - "#endif", - - "uniform sampler2D map;", - "uniform sampler2D occlusionMap;", - "uniform float opacity;", - "uniform int renderType;", - - "varying vec2 vUV;", - - "void main( void )", - "{", - // pink square - - "if( renderType == 0 ) {", - - "gl_FragColor = vec4( texture2D( map, vUV ).rgb, 0.0 );", - - // restore - - "} else if( renderType == 1 ) {", - - "gl_FragColor = texture2D( map, vUV );", - - // flare - - "} else {", - - "float visibility = texture2D( occlusionMap, vec2( 0.5, 0.1 )).a +", - "texture2D( occlusionMap, vec2( 0.9, 0.5 )).a +", - "texture2D( occlusionMap, vec2( 0.5, 0.9 )).a +", - "texture2D( occlusionMap, vec2( 0.1, 0.5 )).a;", - - "visibility = ( 1.0 - visibility / 4.0 );", - - "vec4 color = texture2D( map, vUV );", - "color.a *= opacity * visibility;", - "gl_FragColor = color;", - "}", - "}" - ].join( "\n" ) - - }, - - 'sprite': { - - vertexShader: [ - "uniform int useScreenCoordinates;", - "uniform int affectedByDistance;", - "uniform vec3 screenPosition;", - "uniform mat4 modelViewMatrix;", - "uniform mat4 projectionMatrix;", - "uniform float rotation;", - "uniform vec2 scale;", - "uniform vec2 alignment;", - "uniform vec2 uvOffset;", - "uniform vec2 uvScale;", - - "attribute vec2 position;", - "attribute vec2 uv;", - - "varying vec2 vUV;", - - "void main(void)", - "{", - "vUV = uvOffset + uv * uvScale;", - - "vec2 alignedPosition = position + alignment;", - - "vec2 rotatedPosition;", - "rotatedPosition.x = ( cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y ) * scale.x;", - "rotatedPosition.y = ( sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y ) * scale.y;", - - "vec4 finalPosition;", - - "if( useScreenCoordinates != 0 ) {", - - "finalPosition = vec4( screenPosition.xy + rotatedPosition, screenPosition.z, 1.0 );", - - "} else {", - - "finalPosition = projectionMatrix * modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );", - "finalPosition.xy += rotatedPosition * ( affectedByDistance == 1 ? 1.0 : finalPosition.z );", - - "}", - - "gl_Position = finalPosition;", - "}" - - ].join( "\n" ), - - fragmentShader: [ - - "#ifdef GL_ES", - "precision highp float;", - "#endif", - - "uniform sampler2D map;", - "uniform float opacity;", - - "varying vec2 vUV;", - - "void main( void )", - "{", - "vec4 color = texture2D( map, vUV );", - "color.a *= opacity;", - "gl_FragColor = color;", -// "gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );", - "}" - ].join( "\n" ) - - }, - - - - 'shadowPost': { - - vertexShader: [ - - "uniform mat4 projectionMatrix;", - "attribute vec3 position;", - - "void main(void)", - "{", - "gl_Position = projectionMatrix * vec4( position, 1.0 );", - "}" - - ].join( "\n" ), - - fragmentShader: [ - - "#ifdef GL_ES", - "precision highp float;", - "#endif", - - "uniform float darkness;", - - "void main( void )", - "{", - "gl_FragColor = vec4( 0, 0, 0, darkness );", - "}" - - ].join( "\n" ) - - }, - - - 'shadowVolumeDynamic': { - - uniforms: { "directionalLightDirection": { type: "fv", value: [] }}, - - vertexShader: [ - - "uniform vec3 directionalLightDirection;", - - "void main() {", - - "vec4 pos = objectMatrix * vec4( position, 1.0 );", - "vec3 norm = mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal;", - "vec4 extruded = vec4( directionalLightDirection * 5000.0 * step( 0.0, dot( directionalLightDirection, norm )), 0.0 );", - - "gl_Position = projectionMatrix * viewMatrix * ( pos + extruded );", - "}" - - ].join( "\n" ), - - fragmentShader: [ - - "void main() {", - - "gl_FragColor = vec4( 1.0 );", - - "}" - - ].join( "\n" ) - }, - - - 'depth': { - - uniforms: { "mNear": { type: "f", value: 1.0 }, - "mFar" : { type: "f", value: 2000.0 }, - "opacity" : { type: "f", value: 1.0 } - }, - - fragmentShader: [ - - "uniform float mNear;", - "uniform float mFar;", - "uniform float opacity;", - - "void main() {", - - "float depth = gl_FragCoord.z / gl_FragCoord.w;", - "float color = 1.0 - smoothstep( mNear, mFar, depth );", - "gl_FragColor = vec4( vec3( color ), opacity );", - - "}" - - ].join("\n"), - - vertexShader: [ - - "void main() {", - - "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", - - "}" - - ].join("\n") - - }, - - 'normal': { - - uniforms: { "opacity" : { type: "f", value: 1.0 } }, - - fragmentShader: [ - - "uniform float opacity;", - "varying vec3 vNormal;", - - "void main() {", - - "gl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );", - - "}" - - ].join("\n"), - - vertexShader: [ - - "varying vec3 vNormal;", - - "void main() {", - - "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", - "vNormal = normalize( normalMatrix * normal );", - - "gl_Position = projectionMatrix * mvPosition;", - - "}" - - ].join("\n") - - }, - - 'basic': { - - uniforms: THREE.UniformsLib[ "common" ], - - fragmentShader: [ - - "uniform vec3 diffuse;", - "uniform float opacity;", - - THREE.ShaderChunk[ "color_pars_fragment" ], - THREE.ShaderChunk[ "map_pars_fragment" ], - THREE.ShaderChunk[ "lightmap_pars_fragment" ], - THREE.ShaderChunk[ "envmap_pars_fragment" ], - THREE.ShaderChunk[ "fog_pars_fragment" ], - - "void main() {", - - "gl_FragColor = vec4( diffuse, opacity );", - - THREE.ShaderChunk[ "map_fragment" ], - THREE.ShaderChunk[ "lightmap_fragment" ], - THREE.ShaderChunk[ "color_fragment" ], - THREE.ShaderChunk[ "envmap_fragment" ], - THREE.ShaderChunk[ "fog_fragment" ], - - "}" - - ].join("\n"), - - vertexShader: [ - - THREE.ShaderChunk[ "map_pars_vertex" ], - THREE.ShaderChunk[ "lightmap_pars_vertex" ], - THREE.ShaderChunk[ "envmap_pars_vertex" ], - THREE.ShaderChunk[ "color_pars_vertex" ], - THREE.ShaderChunk[ "skinning_pars_vertex" ], - THREE.ShaderChunk[ "morphtarget_pars_vertex" ], - - "void main() {", - - "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", - - THREE.ShaderChunk[ "map_vertex" ], - THREE.ShaderChunk[ "lightmap_vertex" ], - THREE.ShaderChunk[ "envmap_vertex" ], - THREE.ShaderChunk[ "color_vertex" ], - THREE.ShaderChunk[ "skinning_vertex" ], - THREE.ShaderChunk[ "morphtarget_vertex" ], - THREE.ShaderChunk[ "default_vertex" ], - - "}" - - ].join("\n") - - }, - - 'lambert': { - - uniforms: THREE.UniformsUtils.merge( [ THREE.UniformsLib[ "common" ], THREE.UniformsLib[ "lights" ] ] ), - - fragmentShader: [ - - "uniform vec3 diffuse;", - "uniform float opacity;", - - "varying vec3 vLightWeighting;", - - THREE.ShaderChunk[ "color_pars_fragment" ], - THREE.ShaderChunk[ "map_pars_fragment" ], - THREE.ShaderChunk[ "lightmap_pars_fragment" ], - THREE.ShaderChunk[ "envmap_pars_fragment" ], - THREE.ShaderChunk[ "fog_pars_fragment" ], - - "void main() {", - - "gl_FragColor = vec4( diffuse, opacity );", - "gl_FragColor = gl_FragColor * vec4( vLightWeighting, 1.0 );", - - THREE.ShaderChunk[ "map_fragment" ], - THREE.ShaderChunk[ "lightmap_fragment" ], - THREE.ShaderChunk[ "color_fragment" ], - THREE.ShaderChunk[ "envmap_fragment" ], - THREE.ShaderChunk[ "fog_fragment" ], - - "}" - - ].join("\n"), - - vertexShader: [ - - "varying vec3 vLightWeighting;", - - THREE.ShaderChunk[ "map_pars_vertex" ], - THREE.ShaderChunk[ "lightmap_pars_vertex" ], - THREE.ShaderChunk[ "envmap_pars_vertex" ], - THREE.ShaderChunk[ "lights_pars_vertex" ], - THREE.ShaderChunk[ "color_pars_vertex" ], - THREE.ShaderChunk[ "skinning_pars_vertex" ], - THREE.ShaderChunk[ "morphtarget_pars_vertex" ], - - "void main() {", - - "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", - - THREE.ShaderChunk[ "map_vertex" ], - THREE.ShaderChunk[ "lightmap_vertex" ], - THREE.ShaderChunk[ "envmap_vertex" ], - THREE.ShaderChunk[ "color_vertex" ], - - "vec3 transformedNormal = normalize( normalMatrix * normal );", - - THREE.ShaderChunk[ "lights_vertex" ], - THREE.ShaderChunk[ "skinning_vertex" ], - THREE.ShaderChunk[ "morphtarget_vertex" ], - THREE.ShaderChunk[ "default_vertex" ], - - "}" - - ].join("\n") - - }, - - 'phong': { - - uniforms: THREE.UniformsUtils.merge( [ - - THREE.UniformsLib[ "common" ], - THREE.UniformsLib[ "lights" ], - { - "ambient" : { type: "c", value: new THREE.Color( 0x050505 ) }, - "specular" : { type: "c", value: new THREE.Color( 0x111111 ) }, - "shininess": { type: "f", value: 30 } - } - - ] ), - - fragmentShader: [ - - "uniform vec3 diffuse;", - "uniform float opacity;", - - "uniform vec3 ambient;", - "uniform vec3 specular;", - "uniform float shininess;", - - "varying vec3 vLightWeighting;", - - THREE.ShaderChunk[ "color_pars_fragment" ], - THREE.ShaderChunk[ "map_pars_fragment" ], - THREE.ShaderChunk[ "lightmap_pars_fragment" ], - THREE.ShaderChunk[ "envmap_pars_fragment" ], - THREE.ShaderChunk[ "fog_pars_fragment" ], - THREE.ShaderChunk[ "lights_pars_fragment" ], - - "void main() {", - - "gl_FragColor = vec4( vLightWeighting, 1.0 );", - THREE.ShaderChunk[ "lights_fragment" ], - - THREE.ShaderChunk[ "map_fragment" ], - THREE.ShaderChunk[ "lightmap_fragment" ], - THREE.ShaderChunk[ "color_fragment" ], - THREE.ShaderChunk[ "envmap_fragment" ], - THREE.ShaderChunk[ "fog_fragment" ], - - "}" - - ].join("\n"), - - vertexShader: [ - - "#define PHONG", - - "varying vec3 vLightWeighting;", - "varying vec3 vViewPosition;", - "varying vec3 vNormal;", - - THREE.ShaderChunk[ "map_pars_vertex" ], - THREE.ShaderChunk[ "lightmap_pars_vertex" ], - THREE.ShaderChunk[ "envmap_pars_vertex" ], - THREE.ShaderChunk[ "lights_pars_vertex" ], - THREE.ShaderChunk[ "color_pars_vertex" ], - THREE.ShaderChunk[ "skinning_pars_vertex" ], - THREE.ShaderChunk[ "morphtarget_pars_vertex" ], - - "void main() {", - - "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", - - THREE.ShaderChunk[ "map_vertex" ], - THREE.ShaderChunk[ "lightmap_vertex" ], - THREE.ShaderChunk[ "envmap_vertex" ], - THREE.ShaderChunk[ "color_vertex" ], - - "#ifndef USE_ENVMAP", - "vec4 mPosition = objectMatrix * vec4( position, 1.0 );", - "#endif", - - "vViewPosition = cameraPosition - mPosition.xyz;", - - "vec3 transformedNormal = normalize( normalMatrix * normal );", - "vNormal = transformedNormal;", - - THREE.ShaderChunk[ "lights_vertex" ], - THREE.ShaderChunk[ "skinning_vertex" ], - THREE.ShaderChunk[ "morphtarget_vertex" ], - THREE.ShaderChunk[ "default_vertex" ], - - "}" - - ].join("\n") - - }, - - 'particle_basic': { - - uniforms: THREE.UniformsLib[ "particle" ], - - fragmentShader: [ - - "uniform vec3 psColor;", - "uniform float opacity;", - - THREE.ShaderChunk[ "color_pars_fragment" ], - THREE.ShaderChunk[ "map_particle_pars_fragment" ], - THREE.ShaderChunk[ "fog_pars_fragment" ], - - "void main() {", - - "gl_FragColor = vec4( psColor, opacity );", - - THREE.ShaderChunk[ "map_particle_fragment" ], - THREE.ShaderChunk[ "color_fragment" ], - THREE.ShaderChunk[ "fog_fragment" ], - - "}" - - ].join("\n"), - - vertexShader: [ - - "uniform float size;", - "uniform float scale;", - - THREE.ShaderChunk[ "color_pars_vertex" ], - - "void main() {", - - THREE.ShaderChunk[ "color_vertex" ], - - "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", - - "#ifdef USE_SIZEATTENUATION", - "gl_PointSize = size * ( scale / length( mvPosition.xyz ) );", - "#else", - "gl_PointSize = size;", - "#endif", - - "gl_Position = projectionMatrix * mvPosition;", - - "}" - - ].join("\n") - - } - -}; -/** - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author szimek / https://github.com/szimek/ - */ - -THREE.WebGLRenderer = function ( parameters ) { - - // Currently you can use just up to 4 directional / point lights total. - // Chrome barfs on shader linking when there are more than 4 lights :( - - // The problem comes from shader using too many varying vectors. - - // This is not GPU limitation as the same shader works ok in Firefox - // and Chrome with "--use-gl=desktop" flag. - - // Difference comes from Chrome on Windows using by default ANGLE, - // thus going DirectX9 route (while FF uses OpenGL). - - // See http://code.google.com/p/chromium/issues/detail?id=63491 - - var _this = this, - _gl, _programs = [], - _currentProgram = null, - _currentFramebuffer = null, - _currentDepthMask = true, - - // gl state cache - - _oldDoubleSided = null, - _oldFlipSided = null, - _oldBlending = null, - _oldDepth = null, - _oldPolygonOffset = null; - _oldPolygonOffsetFactor = null; - _oldPolygonOffsetUnits = null; - _cullEnabled = true, - - _viewportX = 0, - _viewportY = 0, - _viewportWidth = 0, - _viewportHeight = 0, - - // camera matrices caches - - _frustum = [ - new THREE.Vector4(), - new THREE.Vector4(), - new THREE.Vector4(), - new THREE.Vector4(), - new THREE.Vector4(), - new THREE.Vector4() - ], - - _projScreenMatrix = new THREE.Matrix4(), - _projectionMatrixArray = new Float32Array( 16 ), - _viewMatrixArray = new Float32Array( 16 ), - - _vector3 = new THREE.Vector4(), - - // light arrays cache - - _lights = { - - ambient: [ 0, 0, 0 ], - directional: { length: 0, colors: new Array(), positions: new Array() }, - point: { length: 0, colors: new Array(), positions: new Array(), distances: new Array() } - - }, - - // parameters - - parameters = parameters || {}, - - _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ), - _stencil = parameters.stencil !== undefined ? parameters.stencil : true, - _antialias = parameters.antialias !== undefined ? parameters.antialias : false, - _clearColor = parameters.clearColor !== undefined ? new THREE.Color( parameters.clearColor ) : new THREE.Color( 0x000000 ), - _clearAlpha = parameters.clearAlpha !== undefined ? parameters.clearAlpha : 0; - - this.data = { - - vertices: 0, - faces: 0, - drawCalls: 0 - - }; - - this.maxMorphTargets = 8; - this.domElement = _canvas; - this.autoClear = true; - this.sortObjects = true; - - // Init GL - - try { - - if ( ! ( _gl = _canvas.getContext( 'experimental-webgl', { antialias: _antialias, stencil: _stencil } ) ) ) { - - throw 'Error creating WebGL context.'; - - } - - } catch ( error ) { - - console.error( error ); - - } - - console.log( - navigator.userAgent + " | " + - _gl.getParameter( _gl.VERSION ) + " | " + - _gl.getParameter( _gl.VENDOR ) + " | " + - _gl.getParameter( _gl.RENDERER ) + " | " + - _gl.getParameter( _gl.SHADING_LANGUAGE_VERSION ) - ); - - _gl.clearColor( 0, 0, 0, 1 ); - _gl.clearDepth( 1 ); - - _gl.enable( _gl.DEPTH_TEST ); - _gl.depthFunc( _gl.LEQUAL ); - - _gl.frontFace( _gl.CCW ); - _gl.cullFace( _gl.BACK ); - _gl.enable( _gl.CULL_FACE ); - - _gl.enable( _gl.BLEND ); - _gl.blendEquation( _gl.FUNC_ADD ); - _gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA ); - - _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha ); - - // _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, true ); - - _cullEnabled = true; - - // - - this.context = _gl; - - var _supportsVertexTextures = ( maxVertexTextures() > 0 ); - - // prepare stencil shadow polygon - - if ( _stencil ) { - - var _stencilShadow = {}; - - _stencilShadow.vertices = new Float32Array( 12 ); - _stencilShadow.faces = new Uint16Array( 6 ); - _stencilShadow.darkness = 0.5; - - _stencilShadow.vertices[ 0 * 3 + 0 ] = -20; _stencilShadow.vertices[ 0 * 3 + 1 ] = -20; _stencilShadow.vertices[ 0 * 3 + 2 ] = -1; - _stencilShadow.vertices[ 1 * 3 + 0 ] = 20; _stencilShadow.vertices[ 1 * 3 + 1 ] = -20; _stencilShadow.vertices[ 1 * 3 + 2 ] = -1; - _stencilShadow.vertices[ 2 * 3 + 0 ] = 20; _stencilShadow.vertices[ 2 * 3 + 1 ] = 20; _stencilShadow.vertices[ 2 * 3 + 2 ] = -1; - _stencilShadow.vertices[ 3 * 3 + 0 ] = -20; _stencilShadow.vertices[ 3 * 3 + 1 ] = 20; _stencilShadow.vertices[ 3 * 3 + 2 ] = -1; - - _stencilShadow.faces[ 0 ] = 0; _stencilShadow.faces[ 1 ] = 1; _stencilShadow.faces[ 2 ] = 2; - _stencilShadow.faces[ 3 ] = 0; _stencilShadow.faces[ 4 ] = 2; _stencilShadow.faces[ 5 ] = 3; - - _stencilShadow.vertexBuffer = _gl.createBuffer(); - _stencilShadow.elementBuffer = _gl.createBuffer(); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, _stencilShadow.vertexBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, _stencilShadow.vertices, _gl.STATIC_DRAW ); - - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _stencilShadow.elementBuffer ); - _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, _stencilShadow.faces, _gl.STATIC_DRAW ); - - _stencilShadow.program = _gl.createProgram(); - - _gl.attachShader( _stencilShadow.program, getShader( "fragment", THREE.ShaderLib.shadowPost.fragmentShader )); - _gl.attachShader( _stencilShadow.program, getShader( "vertex", THREE.ShaderLib.shadowPost.vertexShader )); - - _gl.linkProgram( _stencilShadow.program ); - - _stencilShadow.vertexLocation = _gl.getAttribLocation ( _stencilShadow.program, "position" ); - _stencilShadow.projectionLocation = _gl.getUniformLocation( _stencilShadow.program, "projectionMatrix" ); - _stencilShadow.darknessLocation = _gl.getUniformLocation( _stencilShadow.program, "darkness" ); - } - - - // prepare lens flare - - var _lensFlare = {}; - var i; - - _lensFlare.vertices = new Float32Array( 8 + 8 ); - _lensFlare.faces = new Uint16Array( 6 ); - - i = 0; - _lensFlare.vertices[ i++ ] = -1; _lensFlare.vertices[ i++ ] = -1; // vertex - _lensFlare.vertices[ i++ ] = 0; _lensFlare.vertices[ i++ ] = 0; // uv... etc. - _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = -1; - _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = 0; - _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = 1; - _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = 1; - _lensFlare.vertices[ i++ ] = -1; _lensFlare.vertices[ i++ ] = 1; - _lensFlare.vertices[ i++ ] = 0; _lensFlare.vertices[ i++ ] = 1; - - i = 0; - _lensFlare.faces[ i++ ] = 0; _lensFlare.faces[ i++ ] = 1; _lensFlare.faces[ i++ ] = 2; - _lensFlare.faces[ i++ ] = 0; _lensFlare.faces[ i++ ] = 2; _lensFlare.faces[ i++ ] = 3; - - _lensFlare.vertexBuffer = _gl.createBuffer(); - _lensFlare.elementBuffer = _gl.createBuffer(); - _lensFlare.tempTexture = _gl.createTexture(); - _lensFlare.occlusionTexture = _gl.createTexture(); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, _lensFlare.vertexBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, _lensFlare.vertices, _gl.STATIC_DRAW ); - - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.elementBuffer ); - _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.faces, _gl.STATIC_DRAW ); - - _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture ); - _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGB, 16, 16, 0, _gl.RGB, _gl.UNSIGNED_BYTE, null ); - _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE ); - _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE ); - _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.NEAREST ); - _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.NEAREST ); - - _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.occlusionTexture ); - _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, 16, 16, 0, _gl.RGBA, _gl.UNSIGNED_BYTE, null ); - _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE ); - _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE ); - _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.NEAREST ); - _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.NEAREST ); - - if( _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ) <= 0 ) { - - _lensFlare.hasVertexTexture = false; - - _lensFlare.program = _gl.createProgram(); - _gl.attachShader( _lensFlare.program, getShader( "fragment", THREE.ShaderLib.lensFlare.fragmentShader )); - _gl.attachShader( _lensFlare.program, getShader( "vertex", THREE.ShaderLib.lensFlare.vertexShader )); - _gl.linkProgram( _lensFlare.program ); - - - } else { - - _lensFlare.hasVertexTexture = true; - - _lensFlare.program = _gl.createProgram(); - _gl.attachShader( _lensFlare.program, getShader( "fragment", THREE.ShaderLib.lensFlareVertexTexture.fragmentShader )); - _gl.attachShader( _lensFlare.program, getShader( "vertex", THREE.ShaderLib.lensFlareVertexTexture.vertexShader )); - _gl.linkProgram( _lensFlare.program ); - - } - - _lensFlare.attributes = {}; - _lensFlare.uniforms = {}; - _lensFlare.attributes.vertex = _gl.getAttribLocation ( _lensFlare.program, "position" ); - _lensFlare.attributes.uv = _gl.getAttribLocation ( _lensFlare.program, "UV" ); - _lensFlare.uniforms.renderType = _gl.getUniformLocation( _lensFlare.program, "renderType" ); - _lensFlare.uniforms.map = _gl.getUniformLocation( _lensFlare.program, "map" ); - _lensFlare.uniforms.occlusionMap = _gl.getUniformLocation( _lensFlare.program, "occlusionMap" ); - _lensFlare.uniforms.opacity = _gl.getUniformLocation( _lensFlare.program, "opacity" ); - _lensFlare.uniforms.scale = _gl.getUniformLocation( _lensFlare.program, "scale" ); - _lensFlare.uniforms.rotation = _gl.getUniformLocation( _lensFlare.program, "rotation" ); - _lensFlare.uniforms.screenPosition = _gl.getUniformLocation( _lensFlare.program, "screenPosition" ); - - //_gl.enableVertexAttribArray( _lensFlare.attributes.vertex ); - //_gl.enableVertexAttribArray( _lensFlare.attributes.uv ); - - var _lensFlareAttributesEnabled = false; - - // prepare sprites - - _sprite = {}; - - _sprite.vertices = new Float32Array( 8 + 8 ); - _sprite.faces = new Uint16Array( 6 ); - - i = 0; - _sprite.vertices[ i++ ] = -1; _sprite.vertices[ i++ ] = -1; // vertex - _sprite.vertices[ i++ ] = 0; _sprite.vertices[ i++ ] = 0; // uv... etc. - _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = -1; - _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 0; - _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 1; - _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 1; - _sprite.vertices[ i++ ] = -1; _sprite.vertices[ i++ ] = 1; - _sprite.vertices[ i++ ] = 0; _sprite.vertices[ i++ ] = 1; - - i = 0; - _sprite.faces[ i++ ] = 0; _sprite.faces[ i++ ] = 1; _sprite.faces[ i++ ] = 2; - _sprite.faces[ i++ ] = 0; _sprite.faces[ i++ ] = 2; _sprite.faces[ i++ ] = 3; - - _sprite.vertexBuffer = _gl.createBuffer(); - _sprite.elementBuffer = _gl.createBuffer(); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, _sprite.vertexBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, _sprite.vertices, _gl.STATIC_DRAW ); - - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _sprite.elementBuffer ); - _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, _sprite.faces, _gl.STATIC_DRAW ); - - - _sprite.program = _gl.createProgram(); - _gl.attachShader( _sprite.program, getShader( "fragment", THREE.ShaderLib.sprite.fragmentShader )); - _gl.attachShader( _sprite.program, getShader( "vertex", THREE.ShaderLib.sprite.vertexShader )); - _gl.linkProgram( _sprite.program ); - - _sprite.attributes = {}; - _sprite.uniforms = {}; - _sprite.attributes.position = _gl.getAttribLocation ( _sprite.program, "position" ); - _sprite.attributes.uv = _gl.getAttribLocation ( _sprite.program, "uv" ); - _sprite.uniforms.uvOffset = _gl.getUniformLocation( _sprite.program, "uvOffset" ); - _sprite.uniforms.uvScale = _gl.getUniformLocation( _sprite.program, "uvScale" ); - _sprite.uniforms.rotation = _gl.getUniformLocation( _sprite.program, "rotation" ); - _sprite.uniforms.scale = _gl.getUniformLocation( _sprite.program, "scale" ); - _sprite.uniforms.alignment = _gl.getUniformLocation( _sprite.program, "alignment" ); - _sprite.uniforms.map = _gl.getUniformLocation( _sprite.program, "map" ); - _sprite.uniforms.opacity = _gl.getUniformLocation( _sprite.program, "opacity" ); - _sprite.uniforms.useScreenCoordinates = _gl.getUniformLocation( _sprite.program, "useScreenCoordinates" ); - _sprite.uniforms.affectedByDistance = _gl.getUniformLocation( _sprite.program, "affectedByDistance" ); - _sprite.uniforms.screenPosition = _gl.getUniformLocation( _sprite.program, "screenPosition" ); - _sprite.uniforms.modelViewMatrix = _gl.getUniformLocation( _sprite.program, "modelViewMatrix" ); - _sprite.uniforms.projectionMatrix = _gl.getUniformLocation( _sprite.program, "projectionMatrix" ); - - //_gl.enableVertexAttribArray( _sprite.attributes.position ); - //_gl.enableVertexAttribArray( _sprite.attributes.uv ); - - var _spriteAttributesEnabled = false; - - this.setSize = function ( width, height ) { - - _canvas.width = width; - _canvas.height = height; - - this.setViewport( 0, 0, _canvas.width, _canvas.height ); - - }; - - this.setViewport = function ( x, y, width, height ) { - - _viewportX = x; - _viewportY = y; - - _viewportWidth = width; - _viewportHeight = height; - - _gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight ); - - }; - - this.setScissor = function ( x, y, width, height ) { - - _gl.scissor( x, y, width, height ); - - }; - - this.enableScissorTest = function ( enable ) { - - if ( enable ) - _gl.enable( _gl.SCISSOR_TEST ); - else - _gl.disable( _gl.SCISSOR_TEST ); - - }; - - this.enableDepthBufferWrite = function ( enable ) { - - _currentDepthMask = enable; - _gl.depthMask( enable ); - - }; - - this.setClearColorHex = function ( hex, alpha ) { - - _clearColor.setHex( hex ); - _clearAlpha = alpha; - - _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha ); - - }; - - this.setClearColor = function ( color, alpha ) { - - _clearColor.copy( color ); - _clearAlpha = alpha; - - _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha ); - - }; - - this.clear = function () { - - _gl.clear( _gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT | _gl.STENCIL_BUFFER_BIT ); - - }; - - this.setStencilShadowDarkness = function( value ) { - - _stencilShadow.darkness = value; - }; - - this.getContext = function() { - - return _gl; - - } - - - function setupLights ( program, lights ) { - - var l, ll, light, r = 0, g = 0, b = 0, - color, position, intensity, distance, - - zlights = _lights, - - dcolors = zlights.directional.colors, - dpositions = zlights.directional.positions, - - pcolors = zlights.point.colors, - ppositions = zlights.point.positions, - pdistances = zlights.point.distances, - - dlength = 0, - plength = 0, - - doffset = 0, - poffset = 0; - - for ( l = 0, ll = lights.length; l < ll; l++ ) { - - light = lights[ l ]; - color = light.color; - - position = light.position; - intensity = light.intensity; - distance = light.distance; - - if ( light instanceof THREE.AmbientLight ) { - - r += color.r; - g += color.g; - b += color.b; - - } else if ( light instanceof THREE.DirectionalLight ) { - - doffset = dlength * 3; - - dcolors[ doffset ] = color.r * intensity; - dcolors[ doffset + 1 ] = color.g * intensity; - dcolors[ doffset + 2 ] = color.b * intensity; - - dpositions[ doffset ] = position.x; - dpositions[ doffset + 1 ] = position.y; - dpositions[ doffset + 2 ] = position.z; - - dlength += 1; - - } else if( light instanceof THREE.PointLight ) { - - poffset = plength * 3; - - pcolors[ poffset ] = color.r * intensity; - pcolors[ poffset + 1 ] = color.g * intensity; - pcolors[ poffset + 2 ] = color.b * intensity; - - ppositions[ poffset ] = position.x; - ppositions[ poffset + 1 ] = position.y; - ppositions[ poffset + 2 ] = position.z; - - pdistances[ plength ] = distance; - - plength += 1; - - } - - } - - // null eventual remains from removed lights - // (this is to avoid if in shader) - - for( l = dlength * 3; l < dcolors.length; l++ ) dcolors[ l ] = 0.0; - for( l = plength * 3; l < pcolors.length; l++ ) pcolors[ l ] = 0.0; - - zlights.point.length = plength; - zlights.directional.length = dlength; - - zlights.ambient[ 0 ] = r; - zlights.ambient[ 1 ] = g; - zlights.ambient[ 2 ] = b; - - }; - - function createParticleBuffers ( geometry ) { - - geometry.__webglVertexBuffer = _gl.createBuffer(); - geometry.__webglColorBuffer = _gl.createBuffer(); - - }; - - function createLineBuffers( geometry ) { - - geometry.__webglVertexBuffer = _gl.createBuffer(); - geometry.__webglColorBuffer = _gl.createBuffer(); - - }; - - function createRibbonBuffers( geometry ) { - - geometry.__webglVertexBuffer = _gl.createBuffer(); - geometry.__webglColorBuffer = _gl.createBuffer(); - - }; - - function createMeshBuffers( geometryGroup ) { - - geometryGroup.__webglVertexBuffer = _gl.createBuffer(); - geometryGroup.__webglNormalBuffer = _gl.createBuffer(); - geometryGroup.__webglTangentBuffer = _gl.createBuffer(); - geometryGroup.__webglColorBuffer = _gl.createBuffer(); - geometryGroup.__webglUVBuffer = _gl.createBuffer(); - geometryGroup.__webglUV2Buffer = _gl.createBuffer(); - - geometryGroup.__webglSkinVertexABuffer = _gl.createBuffer(); - geometryGroup.__webglSkinVertexBBuffer = _gl.createBuffer(); - geometryGroup.__webglSkinIndicesBuffer = _gl.createBuffer(); - geometryGroup.__webglSkinWeightsBuffer = _gl.createBuffer(); - - geometryGroup.__webglFaceBuffer = _gl.createBuffer(); - geometryGroup.__webglLineBuffer = _gl.createBuffer(); - - if ( geometryGroup.numMorphTargets ) { - - var m, ml; - geometryGroup.__webglMorphTargetsBuffers = []; - - for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m++ ) { - - geometryGroup.__webglMorphTargetsBuffers.push( _gl.createBuffer() ); - - } - - } - - }; - - function initLineBuffers ( geometry ) { - - var nvertices = geometry.vertices.length; - - geometry.__vertexArray = new Float32Array( nvertices * 3 ); - geometry.__colorArray = new Float32Array( nvertices * 3 ); - - geometry.__webglLineCount = nvertices; - - }; - - function initRibbonBuffers ( geometry ) { - - var nvertices = geometry.vertices.length; - - geometry.__vertexArray = new Float32Array( nvertices * 3 ); - geometry.__colorArray = new Float32Array( nvertices * 3 ); - - geometry.__webglVertexCount = nvertices; - - }; - - function initParticleBuffers ( geometry ) { - - var nvertices = geometry.vertices.length; - - geometry.__vertexArray = new Float32Array( nvertices * 3 ); - geometry.__colorArray = new Float32Array( nvertices * 3 ); - - geometry.__sortArray = []; - - geometry.__webglParticleCount = nvertices; - - }; - - function initMeshBuffers ( geometryGroup, object ) { - - var f, fl, fi, face, - m, ml, size, - nvertices = 0, ntris = 0, nlines = 0, - - uvType, - vertexColorType, - normalType, - materials, material, - attribute, property, originalAttribute, - - geometry = object.geometry, - obj_faces = geometry.faces, - chunk_faces = geometryGroup.faces; - - for ( f = 0, fl = chunk_faces.length; f < fl; f++ ) { - - fi = chunk_faces[ f ]; - face = obj_faces[ fi ]; - - if ( face instanceof THREE.Face3 ) { - - nvertices += 3; - ntris += 1; - nlines += 3; - - } else if ( face instanceof THREE.Face4 ) { - - nvertices += 4; - ntris += 2; - nlines += 4; - - } - - } - - materials = unrollGroupMaterials( geometryGroup, object ); - - // this will not work if materials would change in run-time - // it should be refreshed every frame - // but need to do unrollGroupMaterials - // more properly without push to array - // like unrollBufferMaterials - - geometryGroup.__materials = materials; - - uvType = bufferGuessUVType( materials, geometryGroup, object ); - normalType = bufferGuessNormalType( materials, geometryGroup, object ); - vertexColorType = bufferGuessVertexColorType( materials, geometryGroup, object ); - - //console.log("uvType",uvType, "normalType",normalType, "vertexColorType",vertexColorType, object, geometryGroup, materials ); - - geometryGroup.__vertexArray = new Float32Array( nvertices * 3 ); - - if ( normalType ) { - - geometryGroup.__normalArray = new Float32Array( nvertices * 3 ); - - } - - if ( geometry.hasTangents ) { - - geometryGroup.__tangentArray = new Float32Array( nvertices * 4 ); - - } - - if ( vertexColorType ) { - - geometryGroup.__colorArray = new Float32Array( nvertices * 3 ); - - } - - if ( uvType ) { - - if ( geometry.faceUvs.length > 0 || geometry.faceVertexUvs.length > 0 ) { - - geometryGroup.__uvArray = new Float32Array( nvertices * 2 ); - - } - - if ( geometry.faceUvs.length > 1 || geometry.faceVertexUvs.length > 1 ) { - - geometryGroup.__uv2Array = new Float32Array( nvertices * 2 ); - - } - - } - - if ( object.geometry.skinWeights.length && object.geometry.skinIndices.length ) { - - geometryGroup.__skinVertexAArray = new Float32Array( nvertices * 4 ); - geometryGroup.__skinVertexBArray = new Float32Array( nvertices * 4 ); - geometryGroup.__skinIndexArray = new Float32Array( nvertices * 4 ); - geometryGroup.__skinWeightArray = new Float32Array( nvertices * 4 ); - - } - - geometryGroup.__faceArray = new Uint16Array( ntris * 3 + ( object.geometry.edgeFaces ? object.geometry.edgeFaces.length * 2 * 3 : 0 )); - geometryGroup.__lineArray = new Uint16Array( nlines * 2 ); - - if ( geometryGroup.numMorphTargets ) { - - geometryGroup.__morphTargetsArrays = []; - - for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m++ ) { - - geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) ); - - } - - } - - geometryGroup.__needsSmoothNormals = ( normalType == THREE.SmoothShading ); - - geometryGroup.__uvType = uvType; - geometryGroup.__vertexColorType = vertexColorType; - geometryGroup.__normalType = normalType; - - geometryGroup.__webglFaceCount = ntris * 3 + ( object.geometry.edgeFaces ? object.geometry.edgeFaces.length * 2 * 3 : 0 ); - geometryGroup.__webglLineCount = nlines * 2; - - - // custom attributes - - for ( m = 0, ml = materials.length; m < ml; m ++ ) { - - material = materials[ m ]; - - if ( material.attributes ) { - - geometryGroup.__webglCustomAttributes = {}; - - for ( a in material.attributes ) { - - // Do a shallow copy of the attribute object so different geometryGroup chunks use different - // attribute buffers which are correctly indexed in the setMeshBuffers function - - originalAttribute = material.attributes[ a ]; - - attribute = {}; - - for ( property in originalAttribute ) { - - attribute[ property ] = originalAttribute[ property ]; - - } - - if( !attribute.__webglInitialized || attribute.createUniqueBuffers ) { - - attribute.__webglInitialized = true; - - size = 1; // "f" and "i" - - if( attribute.type === "v2" ) size = 2; - else if( attribute.type === "v3" ) size = 3; - else if( attribute.type === "v4" ) size = 4; - else if( attribute.type === "c" ) size = 3; - - attribute.size = size; - attribute.array = new Float32Array( nvertices * size ); - attribute.buffer = _gl.createBuffer(); - attribute.buffer.belongsToAttribute = a; - - originalAttribute.needsUpdate = true; - attribute.__original = originalAttribute; - - } - - geometryGroup.__webglCustomAttributes[ a ] = attribute; - - } - - } - - } - - geometryGroup.__inittedArrays = true; - - }; - - - function setMeshBuffers ( geometryGroup, object, hint ) { - - if ( ! geometryGroup.__inittedArrays ) { - - // console.log( object ); - return; - - } - - var f, fl, fi, face, - vertexNormals, faceNormal, normal, - vertexColors, faceColor, - vertexTangents, - uvType, vertexColorType, normalType, - uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, - c1, c2, c3, c4, - sw1, sw2, sw3, sw4, - si1, si2, si3, si4, - sa1, sa2, sa3, sa4, - sb1, sb2, sb3, sb4, - m, ml, i, - vn, uvi, uv2i, - vk, vkl, vka, - a, - - vertexIndex = 0, - - offset = 0, - offset_uv = 0, - offset_uv2 = 0, - offset_face = 0, - offset_normal = 0, - offset_tangent = 0, - offset_line = 0, - offset_color = 0, - offset_skin = 0, - offset_morphTarget = 0, - offset_custom = 0, - offset_customSrc = 0, - - vertexArray = geometryGroup.__vertexArray, - uvArray = geometryGroup.__uvArray, - uv2Array = geometryGroup.__uv2Array, - normalArray = geometryGroup.__normalArray, - tangentArray = geometryGroup.__tangentArray, - colorArray = geometryGroup.__colorArray, - - skinVertexAArray = geometryGroup.__skinVertexAArray, - skinVertexBArray = geometryGroup.__skinVertexBArray, - skinIndexArray = geometryGroup.__skinIndexArray, - skinWeightArray = geometryGroup.__skinWeightArray, - - morphTargetsArrays = geometryGroup.__morphTargetsArrays, - - customAttributes = geometryGroup.__webglCustomAttributes, - customAttribute, - - faceArray = geometryGroup.__faceArray, - lineArray = geometryGroup.__lineArray, - - needsSmoothNormals = geometryGroup.__needsSmoothNormals, - - vertexColorType = geometryGroup.__vertexColorType, - uvType = geometryGroup.__uvType, - normalType = geometryGroup.__normalType, - - geometry = object.geometry, // this is shared for all chunks - - dirtyVertices = geometry.__dirtyVertices, - dirtyElements = geometry.__dirtyElements, - dirtyUvs = geometry.__dirtyUvs, - dirtyNormals = geometry.__dirtyNormals, - dirtyTangents = geometry.__dirtyTangents, - dirtyColors = geometry.__dirtyColors, - dirtyMorphTargets = geometry.__dirtyMorphTargets, - - vertices = geometry.vertices, - chunk_faces = geometryGroup.faces, - obj_faces = geometry.faces, - - obj_uvs = geometry.faceVertexUvs[ 0 ], - obj_uvs2 = geometry.faceVertexUvs[ 1 ], - - obj_colors = geometry.colors, - - obj_skinVerticesA = geometry.skinVerticesA, - obj_skinVerticesB = geometry.skinVerticesB, - obj_skinIndices = geometry.skinIndices, - obj_skinWeights = geometry.skinWeights, - obj_edgeFaces = object instanceof THREE.ShadowVolume ? geometry.edgeFaces : undefined, - - morphTargets = geometry.morphTargets; - - if ( customAttributes ) { - - for ( a in customAttributes ) { - - customAttributes[ a ].offset = 0; - customAttributes[ a ].offsetSrc = 0; - - } - - } - - - for ( f = 0, fl = chunk_faces.length; f < fl; f ++ ) { - - fi = chunk_faces[ f ]; - face = obj_faces[ fi ]; - - if ( obj_uvs ) { - - uv = obj_uvs[ fi ]; - - } - - if ( obj_uvs2 ) { - - uv2 = obj_uvs2[ fi ]; - - } - - vertexNormals = face.vertexNormals; - faceNormal = face.normal; - - vertexColors = face.vertexColors; - faceColor = face.color; - - vertexTangents = face.vertexTangents; - - if ( face instanceof THREE.Face3 ) { - - if ( dirtyVertices ) { - - v1 = vertices[ face.a ].position; - v2 = vertices[ face.b ].position; - v3 = vertices[ face.c ].position; - - vertexArray[ offset ] = v1.x; - vertexArray[ offset + 1 ] = v1.y; - vertexArray[ offset + 2 ] = v1.z; - - vertexArray[ offset + 3 ] = v2.x; - vertexArray[ offset + 4 ] = v2.y; - vertexArray[ offset + 5 ] = v2.z; - - vertexArray[ offset + 6 ] = v3.x; - vertexArray[ offset + 7 ] = v3.y; - vertexArray[ offset + 8 ] = v3.z; - - offset += 9; - - } - - if ( customAttributes ) { - - for ( a in customAttributes ) { - - customAttribute = customAttributes[ a ]; - - if ( customAttribute.__original.needsUpdate ) { - - offset_custom = customAttribute.offset; - offset_customSrc = customAttribute.offsetSrc; - - if ( customAttribute.size === 1 ) { - - if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) { - - customAttribute.array[ offset_custom + 0 ] = customAttribute.value[ face.a ]; - customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ]; - customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ]; - - } else if ( customAttribute.boundTo === "faces" ) { - - customAttribute.array[ offset_custom + 0 ] = customAttribute.value[ offset_customSrc ]; - customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ offset_customSrc ]; - customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ offset_customSrc ]; - - customAttribute.offsetSrc ++; - - } else if ( customAttribute.boundTo === "faceVertices" ) { - - customAttribute.array[ offset_custom + 0 ] = customAttribute.value[ offset_customSrc + 0 ]; - customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ offset_customSrc + 1 ]; - customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ offset_customSrc + 2 ]; - - customAttribute.offsetSrc += 3; - - } - - customAttribute.offset += 3; - - } else { - - if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) { - - v1 = customAttribute.value[ face.a ]; - v2 = customAttribute.value[ face.b ]; - v3 = customAttribute.value[ face.c ]; - - } else if ( customAttribute.boundTo === "faces" ) { - - v1 = customAttribute.value[ offset_customSrc ]; - v2 = customAttribute.value[ offset_customSrc ]; - v3 = customAttribute.value[ offset_customSrc ]; - - customAttribute.offsetSrc ++; - - } else if ( customAttribute.boundTo === "faceVertices" ) { - - v1 = customAttribute.value[ offset_customSrc + 0 ]; - v2 = customAttribute.value[ offset_customSrc + 1 ]; - v3 = customAttribute.value[ offset_customSrc + 2 ]; - - customAttribute.offsetSrc += 3; - } - - - if ( customAttribute.size === 2 ) { - - customAttribute.array[ offset_custom + 0 ] = v1.x; - customAttribute.array[ offset_custom + 1 ] = v1.y; - - customAttribute.array[ offset_custom + 2 ] = v2.x; - customAttribute.array[ offset_custom + 3 ] = v2.y; - - customAttribute.array[ offset_custom + 4 ] = v3.x; - customAttribute.array[ offset_custom + 5 ] = v3.y; - - customAttribute.offset += 6; - - } else if ( customAttribute.size === 3 ) { - - if ( customAttribute.type === "c" ) { - - customAttribute.array[ offset_custom + 0 ] = v1.r; - customAttribute.array[ offset_custom + 1 ] = v1.g; - customAttribute.array[ offset_custom + 2 ] = v1.b; - - customAttribute.array[ offset_custom + 3 ] = v2.r; - customAttribute.array[ offset_custom + 4 ] = v2.g; - customAttribute.array[ offset_custom + 5 ] = v2.b; - - customAttribute.array[ offset_custom + 6 ] = v3.r; - customAttribute.array[ offset_custom + 7 ] = v3.g; - customAttribute.array[ offset_custom + 8 ] = v3.b; - - } else { - - customAttribute.array[ offset_custom + 0 ] = v1.x; - customAttribute.array[ offset_custom + 1 ] = v1.y; - customAttribute.array[ offset_custom + 2 ] = v1.z; - - customAttribute.array[ offset_custom + 3 ] = v2.x; - customAttribute.array[ offset_custom + 4 ] = v2.y; - customAttribute.array[ offset_custom + 5 ] = v2.z; - - customAttribute.array[ offset_custom + 6 ] = v3.x; - customAttribute.array[ offset_custom + 7 ] = v3.y; - customAttribute.array[ offset_custom + 8 ] = v3.z; - - } - - customAttribute.offset += 9; - - } else { - - customAttribute.array[ offset_custom + 0 ] = v1.x; - customAttribute.array[ offset_custom + 1 ] = v1.y; - customAttribute.array[ offset_custom + 2 ] = v1.z; - customAttribute.array[ offset_custom + 3 ] = v1.w; - - customAttribute.array[ offset_custom + 4 ] = v2.x; - customAttribute.array[ offset_custom + 5 ] = v2.y; - customAttribute.array[ offset_custom + 6 ] = v2.z; - customAttribute.array[ offset_custom + 7 ] = v2.w; - - customAttribute.array[ offset_custom + 8 ] = v3.x; - customAttribute.array[ offset_custom + 9 ] = v3.y; - customAttribute.array[ offset_custom + 10 ] = v3.z; - customAttribute.array[ offset_custom + 11 ] = v3.w; - - customAttribute.offset += 12; - - } - - } - - } - - } - - } - - - if ( dirtyMorphTargets ) { - - for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) { - - v1 = morphTargets[ vk ].vertices[ face.a ].position; - v2 = morphTargets[ vk ].vertices[ face.b ].position; - v3 = morphTargets[ vk ].vertices[ face.c ].position; - - vka = morphTargetsArrays[ vk ]; - - vka[ offset_morphTarget + 0 ] = v1.x; - vka[ offset_morphTarget + 1 ] = v1.y; - vka[ offset_morphTarget + 2 ] = v1.z; - - vka[ offset_morphTarget + 3 ] = v2.x; - vka[ offset_morphTarget + 4 ] = v2.y; - vka[ offset_morphTarget + 5 ] = v2.z; - - vka[ offset_morphTarget + 6 ] = v3.x; - vka[ offset_morphTarget + 7 ] = v3.y; - vka[ offset_morphTarget + 8 ] = v3.z; - } - - offset_morphTarget += 9; - - } - - if ( obj_skinWeights.length ) { - - // weights - - sw1 = obj_skinWeights[ face.a ]; - sw2 = obj_skinWeights[ face.b ]; - sw3 = obj_skinWeights[ face.c ]; - - skinWeightArray[ offset_skin ] = sw1.x; - skinWeightArray[ offset_skin + 1 ] = sw1.y; - skinWeightArray[ offset_skin + 2 ] = sw1.z; - skinWeightArray[ offset_skin + 3 ] = sw1.w; - - skinWeightArray[ offset_skin + 4 ] = sw2.x; - skinWeightArray[ offset_skin + 5 ] = sw2.y; - skinWeightArray[ offset_skin + 6 ] = sw2.z; - skinWeightArray[ offset_skin + 7 ] = sw2.w; - - skinWeightArray[ offset_skin + 8 ] = sw3.x; - skinWeightArray[ offset_skin + 9 ] = sw3.y; - skinWeightArray[ offset_skin + 10 ] = sw3.z; - skinWeightArray[ offset_skin + 11 ] = sw3.w; - - // indices - - si1 = obj_skinIndices[ face.a ]; - si2 = obj_skinIndices[ face.b ]; - si3 = obj_skinIndices[ face.c ]; - - skinIndexArray[ offset_skin ] = si1.x; - skinIndexArray[ offset_skin + 1 ] = si1.y; - skinIndexArray[ offset_skin + 2 ] = si1.z; - skinIndexArray[ offset_skin + 3 ] = si1.w; - - skinIndexArray[ offset_skin + 4 ] = si2.x; - skinIndexArray[ offset_skin + 5 ] = si2.y; - skinIndexArray[ offset_skin + 6 ] = si2.z; - skinIndexArray[ offset_skin + 7 ] = si2.w; - - skinIndexArray[ offset_skin + 8 ] = si3.x; - skinIndexArray[ offset_skin + 9 ] = si3.y; - skinIndexArray[ offset_skin + 10 ] = si3.z; - skinIndexArray[ offset_skin + 11 ] = si3.w; - - // vertices A - - sa1 = obj_skinVerticesA[ face.a ]; - sa2 = obj_skinVerticesA[ face.b ]; - sa3 = obj_skinVerticesA[ face.c ]; - - skinVertexAArray[ offset_skin ] = sa1.x; - skinVertexAArray[ offset_skin + 1 ] = sa1.y; - skinVertexAArray[ offset_skin + 2 ] = sa1.z; - skinVertexAArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader - - skinVertexAArray[ offset_skin + 4 ] = sa2.x; - skinVertexAArray[ offset_skin + 5 ] = sa2.y; - skinVertexAArray[ offset_skin + 6 ] = sa2.z; - skinVertexAArray[ offset_skin + 7 ] = 1; - - skinVertexAArray[ offset_skin + 8 ] = sa3.x; - skinVertexAArray[ offset_skin + 9 ] = sa3.y; - skinVertexAArray[ offset_skin + 10 ] = sa3.z; - skinVertexAArray[ offset_skin + 11 ] = 1; - - // vertices B - - sb1 = obj_skinVerticesB[ face.a ]; - sb2 = obj_skinVerticesB[ face.b ]; - sb3 = obj_skinVerticesB[ face.c ]; - - skinVertexBArray[ offset_skin ] = sb1.x; - skinVertexBArray[ offset_skin + 1 ] = sb1.y; - skinVertexBArray[ offset_skin + 2 ] = sb1.z; - skinVertexBArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader - - skinVertexBArray[ offset_skin + 4 ] = sb2.x; - skinVertexBArray[ offset_skin + 5 ] = sb2.y; - skinVertexBArray[ offset_skin + 6 ] = sb2.z; - skinVertexBArray[ offset_skin + 7 ] = 1; - - skinVertexBArray[ offset_skin + 8 ] = sb3.x; - skinVertexBArray[ offset_skin + 9 ] = sb3.y; - skinVertexBArray[ offset_skin + 10 ] = sb3.z; - skinVertexBArray[ offset_skin + 11 ] = 1; - - offset_skin += 12; - - } - - if ( dirtyColors && vertexColorType ) { - - if ( vertexColors.length == 3 && vertexColorType == THREE.VertexColors ) { - - c1 = vertexColors[ 0 ]; - c2 = vertexColors[ 1 ]; - c3 = vertexColors[ 2 ]; - - } else { - - c1 = faceColor; - c2 = faceColor; - c3 = faceColor; - - } - - colorArray[ offset_color ] = c1.r; - colorArray[ offset_color + 1 ] = c1.g; - colorArray[ offset_color + 2 ] = c1.b; - - colorArray[ offset_color + 3 ] = c2.r; - colorArray[ offset_color + 4 ] = c2.g; - colorArray[ offset_color + 5 ] = c2.b; - - colorArray[ offset_color + 6 ] = c3.r; - colorArray[ offset_color + 7 ] = c3.g; - colorArray[ offset_color + 8 ] = c3.b; - - offset_color += 9; - - } - - if ( dirtyTangents && geometry.hasTangents ) { - - t1 = vertexTangents[ 0 ]; - t2 = vertexTangents[ 1 ]; - t3 = vertexTangents[ 2 ]; - - tangentArray[ offset_tangent ] = t1.x; - tangentArray[ offset_tangent + 1 ] = t1.y; - tangentArray[ offset_tangent + 2 ] = t1.z; - tangentArray[ offset_tangent + 3 ] = t1.w; - - tangentArray[ offset_tangent + 4 ] = t2.x; - tangentArray[ offset_tangent + 5 ] = t2.y; - tangentArray[ offset_tangent + 6 ] = t2.z; - tangentArray[ offset_tangent + 7 ] = t2.w; - - tangentArray[ offset_tangent + 8 ] = t3.x; - tangentArray[ offset_tangent + 9 ] = t3.y; - tangentArray[ offset_tangent + 10 ] = t3.z; - tangentArray[ offset_tangent + 11 ] = t3.w; - - offset_tangent += 12; - - } - - if ( dirtyNormals && normalType ) { - - if ( vertexNormals.length == 3 && needsSmoothNormals ) { - - for ( i = 0; i < 3; i ++ ) { - - vn = vertexNormals[ i ]; - - normalArray[ offset_normal ] = vn.x; - normalArray[ offset_normal + 1 ] = vn.y; - normalArray[ offset_normal + 2 ] = vn.z; - - offset_normal += 3; - - } - - } else { - - for ( i = 0; i < 3; i ++ ) { - - normalArray[ offset_normal ] = faceNormal.x; - normalArray[ offset_normal + 1 ] = faceNormal.y; - normalArray[ offset_normal + 2 ] = faceNormal.z; - - offset_normal += 3; - - } - - } - - } - - if ( dirtyUvs && uv !== undefined && uvType ) { - - for ( i = 0; i < 3; i ++ ) { - - uvi = uv[ i ]; - - uvArray[ offset_uv ] = uvi.u; - uvArray[ offset_uv + 1 ] = uvi.v; - - offset_uv += 2; - - } - - } - - if ( dirtyUvs && uv2 !== undefined && uvType ) { - - for ( i = 0; i < 3; i ++ ) { - - uv2i = uv2[ i ]; - - uv2Array[ offset_uv2 ] = uv2i.u; - uv2Array[ offset_uv2 + 1 ] = uv2i.v; - - offset_uv2 += 2; - - } - - } - - if ( dirtyElements ) { - - faceArray[ offset_face ] = vertexIndex; - faceArray[ offset_face + 1 ] = vertexIndex + 1; - faceArray[ offset_face + 2 ] = vertexIndex + 2; - - offset_face += 3; - - lineArray[ offset_line ] = vertexIndex; - lineArray[ offset_line + 1 ] = vertexIndex + 1; - - lineArray[ offset_line + 2 ] = vertexIndex; - lineArray[ offset_line + 3 ] = vertexIndex + 2; - - lineArray[ offset_line + 4 ] = vertexIndex + 1; - lineArray[ offset_line + 5 ] = vertexIndex + 2; - - offset_line += 6; - - vertexIndex += 3; - - } - - - } else if ( face instanceof THREE.Face4 ) { - - if ( dirtyVertices ) { - - v1 = vertices[ face.a ].position; - v2 = vertices[ face.b ].position; - v3 = vertices[ face.c ].position; - v4 = vertices[ face.d ].position; - - vertexArray[ offset ] = v1.x; - vertexArray[ offset + 1 ] = v1.y; - vertexArray[ offset + 2 ] = v1.z; - - vertexArray[ offset + 3 ] = v2.x; - vertexArray[ offset + 4 ] = v2.y; - vertexArray[ offset + 5 ] = v2.z; - - vertexArray[ offset + 6 ] = v3.x; - vertexArray[ offset + 7 ] = v3.y; - vertexArray[ offset + 8 ] = v3.z; - - vertexArray[ offset + 9 ] = v4.x; - vertexArray[ offset + 10 ] = v4.y; - vertexArray[ offset + 11 ] = v4.z; - - offset += 12; - - } - - if ( customAttributes ) { - - for ( a in customAttributes ) { - - customAttribute = customAttributes[ a ]; - - if ( customAttribute.__original.needsUpdate ) { - - offset_custom = customAttribute.offset; - offset_customSrc = customAttribute.offsetSrc; - - if ( customAttribute.size === 1 ) { - - if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) { - - customAttribute.array[ offset_custom + 0 ] = customAttribute.value[ face.a ]; - customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ]; - customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ]; - customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ face.d ]; - - } else if ( customAttribute.boundTo === "faces" ) { - - customAttribute.array[ offset_custom + 0 ] = customAttribute.value[ offset_customSrc ]; - customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ offset_customSrc ]; - customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ offset_customSrc ]; - customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ offset_customSrc ]; - - customAttribute.offsetSrc++; - - } else if ( customAttribute.boundTo === "faceVertices" ) { - - customAttribute.array[ offset_custom + 0 ] = customAttribute.value[ offset_customSrc + 0 ]; - customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ offset_customSrc + 1 ]; - customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ offset_customSrc + 2 ]; - customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ offset_customSrc + 3 ]; - - customAttribute.offsetSrc += 4; - } - - customAttribute.offset += 4; - - } else { - - if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) { - - v1 = customAttribute.value[ face.a ]; - v2 = customAttribute.value[ face.b ]; - v3 = customAttribute.value[ face.c ]; - v4 = customAttribute.value[ face.d ]; - - } else if ( customAttribute.boundTo === "faces" ) { - - v1 = customAttribute.value[ offset_customSrc ]; - v2 = customAttribute.value[ offset_customSrc ]; - v3 = customAttribute.value[ offset_customSrc ]; - v4 = customAttribute.value[ offset_customSrc ]; - - customAttribute.offsetSrc++; - - } else if ( customAttribute.boundTo === "faceVertices" ) { - - v1 = customAttribute.value[ offset_customSrc + 0 ]; - v2 = customAttribute.value[ offset_customSrc + 1 ]; - v3 = customAttribute.value[ offset_customSrc + 2 ]; - v4 = customAttribute.value[ offset_customSrc + 3 ]; - - customAttribute.offsetSrc += 4; - } - - - if ( customAttribute.size === 2 ) { - - customAttribute.array[ offset_custom + 0 ] = v1.x; - customAttribute.array[ offset_custom + 1 ] = v1.y; - - customAttribute.array[ offset_custom + 2 ] = v2.x; - customAttribute.array[ offset_custom + 3 ] = v2.y; - - customAttribute.array[ offset_custom + 4 ] = v3.x; - customAttribute.array[ offset_custom + 5 ] = v3.y; - - customAttribute.array[ offset_custom + 6 ] = v4.x; - customAttribute.array[ offset_custom + 7 ] = v4.y; - - customAttribute.offset += 8; - - } else if ( customAttribute.size === 3 ) { - - if ( customAttribute.type === "c" ) { - - customAttribute.array[ offset_custom + 0 ] = v1.r; - customAttribute.array[ offset_custom + 1 ] = v1.g; - customAttribute.array[ offset_custom + 2 ] = v1.b; - - customAttribute.array[ offset_custom + 3 ] = v2.r; - customAttribute.array[ offset_custom + 4 ] = v2.g; - customAttribute.array[ offset_custom + 5 ] = v2.b; - - customAttribute.array[ offset_custom + 6 ] = v3.r; - customAttribute.array[ offset_custom + 7 ] = v3.g; - customAttribute.array[ offset_custom + 8 ] = v3.b; - - customAttribute.array[ offset_custom + 9 ] = v4.r; - customAttribute.array[ offset_custom + 10 ] = v4.g; - customAttribute.array[ offset_custom + 11 ] = v4.b; - - } else { - - customAttribute.array[ offset_custom + 0 ] = v1.x; - customAttribute.array[ offset_custom + 1 ] = v1.y; - customAttribute.array[ offset_custom + 2 ] = v1.z; - - customAttribute.array[ offset_custom + 3 ] = v2.x; - customAttribute.array[ offset_custom + 4 ] = v2.y; - customAttribute.array[ offset_custom + 5 ] = v2.z; - - customAttribute.array[ offset_custom + 6 ] = v3.x; - customAttribute.array[ offset_custom + 7 ] = v3.y; - customAttribute.array[ offset_custom + 8 ] = v3.z; - - customAttribute.array[ offset_custom + 9 ] = v4.x; - customAttribute.array[ offset_custom + 10 ] = v4.y; - customAttribute.array[ offset_custom + 11 ] = v4.z; - - } - - customAttribute.offset += 12; - - } else { - - customAttribute.array[ offset_custom + 0 ] = v1.x; - customAttribute.array[ offset_custom + 1 ] = v1.y; - customAttribute.array[ offset_custom + 2 ] = v1.z; - customAttribute.array[ offset_custom + 3 ] = v1.w; - - customAttribute.array[ offset_custom + 4 ] = v2.x; - customAttribute.array[ offset_custom + 5 ] = v2.y; - customAttribute.array[ offset_custom + 6 ] = v2.z; - customAttribute.array[ offset_custom + 7 ] = v2.w; - - customAttribute.array[ offset_custom + 8 ] = v3.x; - customAttribute.array[ offset_custom + 9 ] = v3.y; - customAttribute.array[ offset_custom + 10 ] = v3.z; - customAttribute.array[ offset_custom + 11 ] = v3.w; - - customAttribute.array[ offset_custom + 12 ] = v4.x; - customAttribute.array[ offset_custom + 13 ] = v4.y; - customAttribute.array[ offset_custom + 14 ] = v4.z; - customAttribute.array[ offset_custom + 15 ] = v4.w; - - customAttribute.offset += 16; - - } - - } - - } - - } - - } - - - if ( dirtyMorphTargets ) { - - for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk++ ) { - - v1 = morphTargets[ vk ].vertices[ face.a ].position; - v2 = morphTargets[ vk ].vertices[ face.b ].position; - v3 = morphTargets[ vk ].vertices[ face.c ].position; - v4 = morphTargets[ vk ].vertices[ face.d ].position; - - vka = morphTargetsArrays[ vk ]; - - vka[ offset_morphTarget + 0 ] = v1.x; - vka[ offset_morphTarget + 1 ] = v1.y; - vka[ offset_morphTarget + 2 ] = v1.z; - - vka[ offset_morphTarget + 3 ] = v2.x; - vka[ offset_morphTarget + 4 ] = v2.y; - vka[ offset_morphTarget + 5 ] = v2.z; - - vka[ offset_morphTarget + 6 ] = v3.x; - vka[ offset_morphTarget + 7 ] = v3.y; - vka[ offset_morphTarget + 8 ] = v3.z; - - vka[ offset_morphTarget + 9 ] = v4.x; - vka[ offset_morphTarget + 10 ] = v4.y; - vka[ offset_morphTarget + 11 ] = v4.z; - } - - offset_morphTarget += 12; - - } - - if ( obj_skinWeights.length ) { - - // weights - - sw1 = obj_skinWeights[ face.a ]; - sw2 = obj_skinWeights[ face.b ]; - sw3 = obj_skinWeights[ face.c ]; - sw4 = obj_skinWeights[ face.d ]; - - skinWeightArray[ offset_skin ] = sw1.x; - skinWeightArray[ offset_skin + 1 ] = sw1.y; - skinWeightArray[ offset_skin + 2 ] = sw1.z; - skinWeightArray[ offset_skin + 3 ] = sw1.w; - - skinWeightArray[ offset_skin + 4 ] = sw2.x; - skinWeightArray[ offset_skin + 5 ] = sw2.y; - skinWeightArray[ offset_skin + 6 ] = sw2.z; - skinWeightArray[ offset_skin + 7 ] = sw2.w; - - skinWeightArray[ offset_skin + 8 ] = sw3.x; - skinWeightArray[ offset_skin + 9 ] = sw3.y; - skinWeightArray[ offset_skin + 10 ] = sw3.z; - skinWeightArray[ offset_skin + 11 ] = sw3.w; - - skinWeightArray[ offset_skin + 12 ] = sw4.x; - skinWeightArray[ offset_skin + 13 ] = sw4.y; - skinWeightArray[ offset_skin + 14 ] = sw4.z; - skinWeightArray[ offset_skin + 15 ] = sw4.w; - - // indices - - si1 = obj_skinIndices[ face.a ]; - si2 = obj_skinIndices[ face.b ]; - si3 = obj_skinIndices[ face.c ]; - si4 = obj_skinIndices[ face.d ]; - - skinIndexArray[ offset_skin ] = si1.x; - skinIndexArray[ offset_skin + 1 ] = si1.y; - skinIndexArray[ offset_skin + 2 ] = si1.z; - skinIndexArray[ offset_skin + 3 ] = si1.w; - - skinIndexArray[ offset_skin + 4 ] = si2.x; - skinIndexArray[ offset_skin + 5 ] = si2.y; - skinIndexArray[ offset_skin + 6 ] = si2.z; - skinIndexArray[ offset_skin + 7 ] = si2.w; - - skinIndexArray[ offset_skin + 8 ] = si3.x; - skinIndexArray[ offset_skin + 9 ] = si3.y; - skinIndexArray[ offset_skin + 10 ] = si3.z; - skinIndexArray[ offset_skin + 11 ] = si3.w; - - skinIndexArray[ offset_skin + 12 ] = si4.x; - skinIndexArray[ offset_skin + 13 ] = si4.y; - skinIndexArray[ offset_skin + 14 ] = si4.z; - skinIndexArray[ offset_skin + 15 ] = si4.w; - - // vertices A - - sa1 = obj_skinVerticesA[ face.a ]; - sa2 = obj_skinVerticesA[ face.b ]; - sa3 = obj_skinVerticesA[ face.c ]; - sa4 = obj_skinVerticesA[ face.d ]; - - skinVertexAArray[ offset_skin ] = sa1.x; - skinVertexAArray[ offset_skin + 1 ] = sa1.y; - skinVertexAArray[ offset_skin + 2 ] = sa1.z; - skinVertexAArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader - - skinVertexAArray[ offset_skin + 4 ] = sa2.x; - skinVertexAArray[ offset_skin + 5 ] = sa2.y; - skinVertexAArray[ offset_skin + 6 ] = sa2.z; - skinVertexAArray[ offset_skin + 7 ] = 1; - - skinVertexAArray[ offset_skin + 8 ] = sa3.x; - skinVertexAArray[ offset_skin + 9 ] = sa3.y; - skinVertexAArray[ offset_skin + 10 ] = sa3.z; - skinVertexAArray[ offset_skin + 11 ] = 1; - - skinVertexAArray[ offset_skin + 12 ] = sa4.x; - skinVertexAArray[ offset_skin + 13 ] = sa4.y; - skinVertexAArray[ offset_skin + 14 ] = sa4.z; - skinVertexAArray[ offset_skin + 15 ] = 1; - - // vertices B - - sb1 = obj_skinVerticesB[ face.a ]; - sb2 = obj_skinVerticesB[ face.b ]; - sb3 = obj_skinVerticesB[ face.c ]; - sb4 = obj_skinVerticesB[ face.d ]; - - skinVertexBArray[ offset_skin ] = sb1.x; - skinVertexBArray[ offset_skin + 1 ] = sb1.y; - skinVertexBArray[ offset_skin + 2 ] = sb1.z; - skinVertexBArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader - - skinVertexBArray[ offset_skin + 4 ] = sb2.x; - skinVertexBArray[ offset_skin + 5 ] = sb2.y; - skinVertexBArray[ offset_skin + 6 ] = sb2.z; - skinVertexBArray[ offset_skin + 7 ] = 1; - - skinVertexBArray[ offset_skin + 8 ] = sb3.x; - skinVertexBArray[ offset_skin + 9 ] = sb3.y; - skinVertexBArray[ offset_skin + 10 ] = sb3.z; - skinVertexBArray[ offset_skin + 11 ] = 1; - - skinVertexBArray[ offset_skin + 12 ] = sb4.x; - skinVertexBArray[ offset_skin + 13 ] = sb4.y; - skinVertexBArray[ offset_skin + 14 ] = sb4.z; - skinVertexBArray[ offset_skin + 15 ] = 1; - - offset_skin += 16; - - } - - if ( dirtyColors && vertexColorType ) { - - if ( vertexColors.length == 4 && vertexColorType == THREE.VertexColors ) { - - c1 = vertexColors[ 0 ]; - c2 = vertexColors[ 1 ]; - c3 = vertexColors[ 2 ]; - c4 = vertexColors[ 3 ]; - - } else { - - c1 = faceColor; - c2 = faceColor; - c3 = faceColor; - c4 = faceColor; - - } - - colorArray[ offset_color ] = c1.r; - colorArray[ offset_color + 1 ] = c1.g; - colorArray[ offset_color + 2 ] = c1.b; - - colorArray[ offset_color + 3 ] = c2.r; - colorArray[ offset_color + 4 ] = c2.g; - colorArray[ offset_color + 5 ] = c2.b; - - colorArray[ offset_color + 6 ] = c3.r; - colorArray[ offset_color + 7 ] = c3.g; - colorArray[ offset_color + 8 ] = c3.b; - - colorArray[ offset_color + 9 ] = c4.r; - colorArray[ offset_color + 10 ] = c4.g; - colorArray[ offset_color + 11 ] = c4.b; - - offset_color += 12; - - } - - if ( dirtyTangents && geometry.hasTangents ) { - - t1 = vertexTangents[ 0 ]; - t2 = vertexTangents[ 1 ]; - t3 = vertexTangents[ 2 ]; - t4 = vertexTangents[ 3 ]; - - tangentArray[ offset_tangent ] = t1.x; - tangentArray[ offset_tangent + 1 ] = t1.y; - tangentArray[ offset_tangent + 2 ] = t1.z; - tangentArray[ offset_tangent + 3 ] = t1.w; - - tangentArray[ offset_tangent + 4 ] = t2.x; - tangentArray[ offset_tangent + 5 ] = t2.y; - tangentArray[ offset_tangent + 6 ] = t2.z; - tangentArray[ offset_tangent + 7 ] = t2.w; - - tangentArray[ offset_tangent + 8 ] = t3.x; - tangentArray[ offset_tangent + 9 ] = t3.y; - tangentArray[ offset_tangent + 10 ] = t3.z; - tangentArray[ offset_tangent + 11 ] = t3.w; - - tangentArray[ offset_tangent + 12 ] = t4.x; - tangentArray[ offset_tangent + 13 ] = t4.y; - tangentArray[ offset_tangent + 14 ] = t4.z; - tangentArray[ offset_tangent + 15 ] = t4.w; - - offset_tangent += 16; - - } - - if ( dirtyNormals && normalType ) { - - if ( vertexNormals.length == 4 && needsSmoothNormals ) { - - for ( i = 0; i < 4; i ++ ) { - - vn = vertexNormals[ i ]; - - normalArray[ offset_normal ] = vn.x; - normalArray[ offset_normal + 1 ] = vn.y; - normalArray[ offset_normal + 2 ] = vn.z; - - offset_normal += 3; - - } - - } else { - - for ( i = 0; i < 4; i ++ ) { - - normalArray[ offset_normal ] = faceNormal.x; - normalArray[ offset_normal + 1 ] = faceNormal.y; - normalArray[ offset_normal + 2 ] = faceNormal.z; - - offset_normal += 3; - - } - - } - - } - - if ( dirtyUvs && uv !== undefined && uvType ) { - - for ( i = 0; i < 4; i ++ ) { - - uvi = uv[ i ]; - - uvArray[ offset_uv ] = uvi.u; - uvArray[ offset_uv + 1 ] = uvi.v; - - offset_uv += 2; - - } - - } - - if ( dirtyUvs && uv2 !== undefined && uvType ) { - - for ( i = 0; i < 4; i ++ ) { - - uv2i = uv2[ i ]; - - uv2Array[ offset_uv2 ] = uv2i.u; - uv2Array[ offset_uv2 + 1 ] = uv2i.v; - - offset_uv2 += 2; - - } - - } - - if ( dirtyElements ) { - - faceArray[ offset_face ] = vertexIndex; - faceArray[ offset_face + 1 ] = vertexIndex + 1; - faceArray[ offset_face + 2 ] = vertexIndex + 3; - - faceArray[ offset_face + 3 ] = vertexIndex + 1; - faceArray[ offset_face + 4 ] = vertexIndex + 2; - faceArray[ offset_face + 5 ] = vertexIndex + 3; - - offset_face += 6; - - lineArray[ offset_line ] = vertexIndex; - lineArray[ offset_line + 1 ] = vertexIndex + 1; - - lineArray[ offset_line + 2 ] = vertexIndex; - lineArray[ offset_line + 3 ] = vertexIndex + 3; - - lineArray[ offset_line + 4 ] = vertexIndex + 1; - lineArray[ offset_line + 5 ] = vertexIndex + 2; - - lineArray[ offset_line + 6 ] = vertexIndex + 2; - lineArray[ offset_line + 7 ] = vertexIndex + 3; - - offset_line += 8; - - vertexIndex += 4; - - } - - } - - } - - if ( obj_edgeFaces ) { - - for ( f = 0, fl = obj_edgeFaces.length; f < fl; f ++ ) { - - faceArray[ offset_face ] = obj_edgeFaces[ f ].a; - faceArray[ offset_face + 1 ] = obj_edgeFaces[ f ].b; - faceArray[ offset_face + 2 ] = obj_edgeFaces[ f ].c; - - faceArray[ offset_face + 3 ] = obj_edgeFaces[ f ].a; - faceArray[ offset_face + 4 ] = obj_edgeFaces[ f ].c; - faceArray[ offset_face + 5 ] = obj_edgeFaces[ f ].d; - - offset_face += 6; - } - - } - - if ( dirtyVertices ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint ); - - } - - if ( customAttributes ) { - - for ( a in customAttributes ) { - - customAttribute = customAttributes[ a ]; - - if ( customAttribute.__original.needsUpdate ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint ); - - } - - } - - } - - if ( dirtyMorphTargets ) { - - for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ vk ] ); - _gl.bufferData( _gl.ARRAY_BUFFER, morphTargetsArrays[ vk ], hint ); - - } - } - - if ( dirtyColors && offset_color > 0 ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint ); - - } - - if ( dirtyNormals ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, normalArray, hint ); - - } - - if ( dirtyTangents && geometry.hasTangents ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, tangentArray, hint ); - - } - - if ( dirtyUvs && offset_uv > 0 ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, uvArray, hint ); - - } - - if ( dirtyUvs && offset_uv2 > 0 ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, uv2Array, hint ); - - } - - if ( dirtyElements ) { - - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer ); - _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, faceArray, hint ); - - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer ); - _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, lineArray, hint ); - - } - - if ( offset_skin > 0 ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexABuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, skinVertexAArray, hint ); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexBBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, skinVertexBArray, hint ); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, skinIndexArray, hint ); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, skinWeightArray, hint ); - - } - - if ( ! object.dynamic ) { - - delete geometryGroup.__inittedArrays; - delete geometryGroup.__colorArray; - delete geometryGroup.__normalArray; - delete geometryGroup.__tangentArray; - delete geometryGroup.__uvArray; - delete geometryGroup.__uv2Array; - delete geometryGroup.__faceArray; - delete geometryGroup.__vertexArray; - delete geometryGroup.__lineArray; - delete geometryGroup.__skinVertexAArray; - delete geometryGroup.__skinVertexBArray; - delete geometryGroup.__skinIndexArray; - delete geometryGroup.__skinWeightArray; - - } - - }; - - function setLineBuffers ( geometry, hint ) { - - var v, c, vertex, offset, - vertices = geometry.vertices, - colors = geometry.colors, - vl = vertices.length, - cl = colors.length, - - vertexArray = geometry.__vertexArray, - colorArray = geometry.__colorArray, - - dirtyVertices = geometry.__dirtyVertices, - dirtyColors = geometry.__dirtyColors; - - if ( dirtyVertices ) { - - for ( v = 0; v < vl; v++ ) { - - vertex = vertices[ v ].position; - - offset = v * 3; - - vertexArray[ offset ] = vertex.x; - vertexArray[ offset + 1 ] = vertex.y; - vertexArray[ offset + 2 ] = vertex.z; - - } - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint ); - - } - - if ( dirtyColors ) { - - for ( c = 0; c < cl; c++ ) { - - color = colors[ c ]; - - offset = c * 3; - - colorArray[ offset ] = color.r; - colorArray[ offset + 1 ] = color.g; - colorArray[ offset + 2 ] = color.b; - - } - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint ); - - } - - }; - - function setRibbonBuffers ( geometry, hint ) { - - var v, c, vertex, offset, - vertices = geometry.vertices, - colors = geometry.colors, - vl = vertices.length, - cl = colors.length, - - vertexArray = geometry.__vertexArray, - colorArray = geometry.__colorArray, - - dirtyVertices = geometry.__dirtyVertices, - dirtyColors = geometry.__dirtyColors; - - if ( dirtyVertices ) { - - for ( v = 0; v < vl; v++ ) { - - vertex = vertices[ v ].position; - - offset = v * 3; - - vertexArray[ offset ] = vertex.x; - vertexArray[ offset + 1 ] = vertex.y; - vertexArray[ offset + 2 ] = vertex.z; - - } - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint ); - - } - - if ( dirtyColors ) { - - for ( c = 0; c < cl; c++ ) { - - color = colors[ c ]; - - offset = c * 3; - - colorArray[ offset ] = color.r; - colorArray[ offset + 1 ] = color.g; - colorArray[ offset + 2 ] = color.b; - - } - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint ); - - } - - }; - - function setParticleBuffers ( geometry, hint, object ) { - - var v, c, vertex, offset, - vertices = geometry.vertices, - vl = vertices.length, - - colors = geometry.colors, - cl = colors.length, - - vertexArray = geometry.__vertexArray, - colorArray = geometry.__colorArray, - - sortArray = geometry.__sortArray, - - dirtyVertices = geometry.__dirtyVertices, - dirtyElements = geometry.__dirtyElements, - dirtyColors = geometry.__dirtyColors; - - if ( object.sortParticles ) { - - _projScreenMatrix.multiplySelf( object.matrixWorld ); - - for ( v = 0; v < vl; v++ ) { - - vertex = vertices[ v ].position; - - _vector3.copy( vertex ); - _projScreenMatrix.multiplyVector3( _vector3 ); - - sortArray[ v ] = [ _vector3.z, v ]; - - } - - sortArray.sort( function(a,b) { return b[0] - a[0]; } ); - - for ( v = 0; v < vl; v++ ) { - - vertex = vertices[ sortArray[v][1] ].position; - - offset = v * 3; - - vertexArray[ offset ] = vertex.x; - vertexArray[ offset + 1 ] = vertex.y; - vertexArray[ offset + 2 ] = vertex.z; - - } - - for ( c = 0; c < cl; c++ ) { - - offset = c * 3; - - color = colors[ sortArray[c][1] ]; - - colorArray[ offset ] = color.r; - colorArray[ offset + 1 ] = color.g; - colorArray[ offset + 2 ] = color.b; - - } - - - } else { - - if ( dirtyVertices ) { - - for ( v = 0; v < vl; v++ ) { - - vertex = vertices[ v ].position; - - offset = v * 3; - - vertexArray[ offset ] = vertex.x; - vertexArray[ offset + 1 ] = vertex.y; - vertexArray[ offset + 2 ] = vertex.z; - - } - - } - - if ( dirtyColors ) { - - for ( c = 0; c < cl; c++ ) { - - color = colors[ c ]; - - offset = c * 3; - - colorArray[ offset ] = color.r; - colorArray[ offset + 1 ] = color.g; - colorArray[ offset + 2 ] = color.b; - - } - - } - - } - - if ( dirtyVertices || object.sortParticles ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint ); - - } - - if ( dirtyColors || object.sortParticles ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint ); - - } - - }; - - function setMaterialShaders( material, shaders ) { - - material.uniforms = THREE.UniformsUtils.clone( shaders.uniforms ); - material.vertexShader = shaders.vertexShader; - material.fragmentShader = shaders.fragmentShader; - - }; - - function refreshUniformsCommon( uniforms, material ) { - - uniforms.diffuse.value = material.color; - uniforms.opacity.value = material.opacity; - - uniforms.map.texture = material.map; - if ( material.map ) { - - uniforms.offsetRepeat.value.set( material.map.offset.x, material.map.offset.y, material.map.repeat.x, material.map.repeat.y ); - - } - - uniforms.lightMap.texture = material.lightMap; - - uniforms.envMap.texture = material.envMap; - uniforms.reflectivity.value = material.reflectivity; - uniforms.refractionRatio.value = material.refractionRatio; - uniforms.combine.value = material.combine; - uniforms.useRefract.value = material.envMap && material.envMap.mapping instanceof THREE.CubeRefractionMapping; - - }; - - function refreshUniformsLine( uniforms, material ) { - - uniforms.diffuse.value = material.color; - uniforms.opacity.value = material.opacity; - - }; - - function refreshUniformsParticle( uniforms, material ) { - - uniforms.psColor.value = material.color; - uniforms.opacity.value = material.opacity; - uniforms.size.value = material.size; - uniforms.scale.value = _canvas.height / 2.0; // TODO: Cache this. - - uniforms.map.texture = material.map; - - }; - - function refreshUniformsFog( uniforms, fog ) { - - uniforms.fogColor.value = fog.color; - - if ( fog instanceof THREE.Fog ) { - - uniforms.fogNear.value = fog.near; - uniforms.fogFar.value = fog.far; - - } else if ( fog instanceof THREE.FogExp2 ) { - - uniforms.fogDensity.value = fog.density; - - } - - }; - - function refreshUniformsPhong( uniforms, material ) { - - uniforms.ambient.value = material.ambient; - uniforms.specular.value = material.specular; - uniforms.shininess.value = material.shininess; - - }; - - - function refreshUniformsLights( uniforms, lights ) { - - uniforms.enableLighting.value = lights.directional.length + lights.point.length; - uniforms.ambientLightColor.value = lights.ambient; - - uniforms.directionalLightColor.value = lights.directional.colors; - uniforms.directionalLightDirection.value = lights.directional.positions; - - uniforms.pointLightColor.value = lights.point.colors; - uniforms.pointLightPosition.value = lights.point.positions; - uniforms.pointLightDistance.value = lights.point.distances; - - }; - - this.initMaterial = function ( material, lights, fog, object ) { - - var u, a, identifiers, i, parameters, maxLightCount, maxBones, shaderID; - - if ( material instanceof THREE.MeshDepthMaterial ) { - - shaderID = 'depth'; - - } else if ( material instanceof THREE.ShadowVolumeDynamicMaterial ) { - - shaderID = 'shadowVolumeDynamic'; - - } else if ( material instanceof THREE.MeshNormalMaterial ) { - - shaderID = 'normal'; - - } else if ( material instanceof THREE.MeshBasicMaterial ) { - - shaderID = 'basic'; - - } else if ( material instanceof THREE.MeshLambertMaterial ) { - - shaderID = 'lambert'; - - } else if ( material instanceof THREE.MeshPhongMaterial ) { - - shaderID = 'phong'; - - } else if ( material instanceof THREE.LineBasicMaterial ) { - - shaderID = 'basic'; - - } else if ( material instanceof THREE.ParticleBasicMaterial ) { - - shaderID = 'particle_basic'; - - } - - if ( shaderID ) { - - setMaterialShaders( material, THREE.ShaderLib[ shaderID ] ); - - } - - // heuristics to create shader parameters according to lights in the scene - // (not to blow over maxLights budget) - - maxLightCount = allocateLights( lights, 4 ); - - maxBones = allocateBones( object ); - - parameters = { - map: !!material.map, envMap: !!material.envMap, lightMap: !!material.lightMap, - vertexColors: material.vertexColors, - fog: fog, sizeAttenuation: material.sizeAttenuation, - skinning: material.skinning, - morphTargets: material.morphTargets, - maxMorphTargets: this.maxMorphTargets, - maxDirLights: maxLightCount.directional, maxPointLights: maxLightCount.point, - maxBones: maxBones - }; - - material.program = buildProgram( shaderID, material.fragmentShader, material.vertexShader, material.uniforms, material.attributes, parameters ); - - var attributes = material.program.attributes; - - if ( attributes.position >= 0 ) _gl.enableVertexAttribArray( attributes.position ); - if ( attributes.color >= 0 ) _gl.enableVertexAttribArray( attributes.color ); - if ( attributes.normal >= 0 ) _gl.enableVertexAttribArray( attributes.normal ); - if ( attributes.tangent >= 0 ) _gl.enableVertexAttribArray( attributes.tangent ); - - if ( material.skinning && - attributes.skinVertexA >=0 && attributes.skinVertexB >= 0 && - attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) { - - _gl.enableVertexAttribArray( attributes.skinVertexA ); - _gl.enableVertexAttribArray( attributes.skinVertexB ); - _gl.enableVertexAttribArray( attributes.skinIndex ); - _gl.enableVertexAttribArray( attributes.skinWeight ); - - } - - if ( material.attributes ) { - - for ( a in material.attributes ) { - - if( attributes[ a ] !== undefined && attributes[ a ] >= 0 ) _gl.enableVertexAttribArray( attributes[ a ] ); - - } - - } - - - - if ( material.morphTargets ) { - - material.numSupportedMorphTargets = 0; - - - if ( attributes.morphTarget0 >= 0 ) { - - _gl.enableVertexAttribArray( attributes.morphTarget0 ); - material.numSupportedMorphTargets ++; - - } - - if ( attributes.morphTarget1 >= 0 ) { - - _gl.enableVertexAttribArray( attributes.morphTarget1 ); - material.numSupportedMorphTargets ++; - - } - - if ( attributes.morphTarget2 >= 0 ) { - - _gl.enableVertexAttribArray( attributes.morphTarget2 ); - material.numSupportedMorphTargets ++; - - } - - if ( attributes.morphTarget3 >= 0 ) { - - _gl.enableVertexAttribArray( attributes.morphTarget3 ); - material.numSupportedMorphTargets ++; - - } - - if ( attributes.morphTarget4 >= 0 ) { - - _gl.enableVertexAttribArray( attributes.morphTarget4 ); - material.numSupportedMorphTargets ++; - - } - - if ( attributes.morphTarget5 >= 0 ) { - - _gl.enableVertexAttribArray( attributes.morphTarget5 ); - material.numSupportedMorphTargets ++; - - } - - if ( attributes.morphTarget6 >= 0 ) { - - _gl.enableVertexAttribArray( attributes.morphTarget6 ); - material.numSupportedMorphTargets ++; - - } - - if ( attributes.morphTarget7 >= 0 ) { - - _gl.enableVertexAttribArray( attributes.morphTarget7 ); - material.numSupportedMorphTargets ++; - - } - - object.__webglMorphTargetInfluences = new Float32Array( this.maxMorphTargets ); - - for ( var i = 0, il = this.maxMorphTargets; i < il; i ++ ) { - - object.__webglMorphTargetInfluences[ i ] = 0; - - } - - } - - }; - - function setProgram( camera, lights, fog, material, object ) { - - if ( ! material.program ) { - - _this.initMaterial( material, lights, fog, object ); - - } - - var program = material.program, - p_uniforms = program.uniforms, - m_uniforms = material.uniforms; - - if ( program != _currentProgram ) { - - _gl.useProgram( program ); - _currentProgram = program; - - } - - _gl.uniformMatrix4fv( p_uniforms.projectionMatrix, false, _projectionMatrixArray ); - - // refresh uniforms common to several materials - - if ( fog && ( - material instanceof THREE.MeshBasicMaterial || - material instanceof THREE.MeshLambertMaterial || - material instanceof THREE.MeshPhongMaterial || - material instanceof THREE.LineBasicMaterial || - material instanceof THREE.ParticleBasicMaterial || - material.fog ) - ) { - - refreshUniformsFog( m_uniforms, fog ); - - } - - if ( material instanceof THREE.MeshPhongMaterial || - material instanceof THREE.MeshLambertMaterial || - material.lights ) { - - setupLights( program, lights ); - refreshUniformsLights( m_uniforms, _lights ); - - } - - if ( material instanceof THREE.MeshBasicMaterial || - material instanceof THREE.MeshLambertMaterial || - material instanceof THREE.MeshPhongMaterial ) { - - refreshUniformsCommon( m_uniforms, material ); - - } - - // refresh single material specific uniforms - - if ( material instanceof THREE.LineBasicMaterial ) { - - refreshUniformsLine( m_uniforms, material ); - - } else if ( material instanceof THREE.ParticleBasicMaterial ) { - - refreshUniformsParticle( m_uniforms, material ); - - } else if ( material instanceof THREE.MeshPhongMaterial ) { - - refreshUniformsPhong( m_uniforms, material ); - - } else if ( material instanceof THREE.MeshDepthMaterial ) { - - m_uniforms.mNear.value = camera.near; - m_uniforms.mFar.value = camera.far; - m_uniforms.opacity.value = material.opacity; - - } else if ( material instanceof THREE.MeshNormalMaterial ) { - - m_uniforms.opacity.value = material.opacity; - } - - // load common uniforms - - loadUniformsGeneric( program, m_uniforms ); - loadUniformsMatrices( p_uniforms, object ); - - // load material specific uniforms - // (shader material also gets them for the sake of genericity) - - if ( material instanceof THREE.MeshShaderMaterial || - material instanceof THREE.MeshPhongMaterial || - material.envMap ) { - - if( p_uniforms.cameraPosition !== null ) { - - _gl.uniform3f( p_uniforms.cameraPosition, camera.position.x, camera.position.y, camera.position.z ); - - } - - } - - if ( material instanceof THREE.MeshShaderMaterial || - material.envMap || - material.skinning ) { - - if ( p_uniforms.objectMatrix !== null ) { - - _gl.uniformMatrix4fv( p_uniforms.objectMatrix, false, object._objectMatrixArray ); - - } - - } - - if ( material instanceof THREE.MeshPhongMaterial || - material instanceof THREE.MeshLambertMaterial || - material instanceof THREE.MeshShaderMaterial || - material.skinning ) { - - if( p_uniforms.viewMatrix !== null ) { - - _gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, _viewMatrixArray ); - - } - - } - - if ( material instanceof THREE.ShadowVolumeDynamicMaterial ) { - - var dirLight = m_uniforms.directionalLightDirection.value; - - dirLight[ 0 ] = -lights[ 1 ].position.x; - dirLight[ 1 ] = -lights[ 1 ].position.y; - dirLight[ 2 ] = -lights[ 1 ].position.z; - - _gl.uniform3fv( p_uniforms.directionalLightDirection, dirLight ); - _gl.uniformMatrix4fv( p_uniforms.objectMatrix, false, object._objectMatrixArray ); - _gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, _viewMatrixArray ); - } - - - if ( material.skinning ) { - - loadUniformsSkinning( p_uniforms, object ); - - } - - return program; - - }; - - function renderBuffer( camera, lights, fog, material, geometryGroup, object ) { - - if ( material.opacity == 0 ) return; - - var program, attributes, linewidth, primitives, a, attribute; - - program = setProgram( camera, lights, fog, material, object ); - - attributes = program.attributes; - - // vertices - - if ( !material.morphTargets && attributes.position >= 0 ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer ); - _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 ); - - } else { - - setupMorphTargets( material, geometryGroup, object ); - - } - - - // custom attributes - - // Use the per-geometryGroup custom attribute arrays which are setup in initMeshBuffers - - if ( geometryGroup.__webglCustomAttributes ) { - - for( a in geometryGroup.__webglCustomAttributes ) { - - if( attributes[ a ] >= 0 ) { - - attribute = geometryGroup.__webglCustomAttributes[ a ]; - - _gl.bindBuffer( _gl.ARRAY_BUFFER, attribute.buffer ); - _gl.vertexAttribPointer( attributes[ a ], attribute.size, _gl.FLOAT, false, 0, 0 ); - - } - - } - - } - - -/* if ( material.attributes ) { - - for( a in material.attributes ) { - - if( attributes[ a ] !== undefined && attributes[ a ] >= 0 ) { - - attribute = material.attributes[ a ]; - - if( attribute.buffer ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, attribute.buffer ); - _gl.vertexAttribPointer( attributes[ a ], attribute.size, _gl.FLOAT, false, 0, 0 ); - - } - - } - - } - - }*/ - - - - // colors - - if ( attributes.color >= 0 ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer ); - _gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 ); - - } - - // normals - - if ( attributes.normal >= 0 ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer ); - _gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 ); - - } - - // tangents - - if ( attributes.tangent >= 0 ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer ); - _gl.vertexAttribPointer( attributes.tangent, 4, _gl.FLOAT, false, 0, 0 ); - - } - - // uvs - - if ( attributes.uv >= 0 ) { - - if ( geometryGroup.__webglUVBuffer ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer ); - _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 ); - - _gl.enableVertexAttribArray( attributes.uv ); - - } else { - - _gl.disableVertexAttribArray( attributes.uv ); - - } - - } - - if ( attributes.uv2 >= 0 ) { - - if ( geometryGroup.__webglUV2Buffer ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer ); - _gl.vertexAttribPointer( attributes.uv2, 2, _gl.FLOAT, false, 0, 0 ); - - _gl.enableVertexAttribArray( attributes.uv2 ); - - } else { - - _gl.disableVertexAttribArray( attributes.uv2 ); - - } - - } - - if ( material.skinning && - attributes.skinVertexA >= 0 && attributes.skinVertexB >= 0 && - attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexABuffer ); - _gl.vertexAttribPointer( attributes.skinVertexA, 4, _gl.FLOAT, false, 0, 0 ); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexBBuffer ); - _gl.vertexAttribPointer( attributes.skinVertexB, 4, _gl.FLOAT, false, 0, 0 ); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer ); - _gl.vertexAttribPointer( attributes.skinIndex, 4, _gl.FLOAT, false, 0, 0 ); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer ); - _gl.vertexAttribPointer( attributes.skinWeight, 4, _gl.FLOAT, false, 0, 0 ); - - } - - // render mesh - - if ( object instanceof THREE.Mesh ) { - - // wireframe - - if ( material.wireframe ) { - - _gl.lineWidth( material.wireframeLinewidth ); - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer ); - _gl.drawElements( _gl.LINES, geometryGroup.__webglLineCount, _gl.UNSIGNED_SHORT, 0 ); - - // triangles - - } else { - - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer ); - _gl.drawElements( _gl.TRIANGLES, geometryGroup.__webglFaceCount, _gl.UNSIGNED_SHORT, 0 ); - - } - - _this.data.vertices += geometryGroup.__webglFaceCount; - _this.data.faces += geometryGroup.__webglFaceCount / 3; - _this.data.drawCalls ++; - - // render lines - - } else if ( object instanceof THREE.Line ) { - - primitives = ( object.type == THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES; - - _gl.lineWidth( material.linewidth ); - _gl.drawArrays( primitives, 0, geometryGroup.__webglLineCount ); - - _this.data.drawCalls ++; - - // render particles - - } else if ( object instanceof THREE.ParticleSystem ) { - - _gl.drawArrays( _gl.POINTS, 0, geometryGroup.__webglParticleCount ); - - _this.data.drawCalls ++; - - // render ribbon - - } else if ( object instanceof THREE.Ribbon ) { - - _gl.drawArrays( _gl.TRIANGLE_STRIP, 0, geometryGroup.__webglVertexCount ); - - _this.data.drawCalls ++; - - } - - }; - - - function setupMorphTargets( material, geometryGroup, object ) { - - // set base - - var attributes = material.program.attributes; - - if ( object.morphTargetBase !== - 1 ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ object.morphTargetBase ] ); - _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 ); - - } else if ( attributes.position >= 0 ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer ); - _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 ); - - } - - if ( object.morphTargetForcedOrder.length ) { - - // set forced order - - var m = 0; - var order = object.morphTargetForcedOrder; - var influences = object.morphTargetInfluences; - - while ( m < material.numSupportedMorphTargets && m < order.length ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ order[ m ] ] ); - _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 ); - - object.__webglMorphTargetInfluences[ m ] = influences[ order[ m ]]; - - m ++; - } - - } else { - - // find most influencing - - var used = []; - var candidateInfluence = - 1; - var candidate = 0; - var influences = object.morphTargetInfluences; - var i, il = influences.length; - var m = 0; - - if ( object.morphTargetBase !== - 1 ) { - - used[ object.morphTargetBase ] = true; - - } - - while ( m < material.numSupportedMorphTargets ) { - - for ( i = 0; i < il; i ++ ) { - - if ( !used[ i ] && influences[ i ] > candidateInfluence ) { - - candidate = i; - candidateInfluence = influences[ candidate ]; - - } - } - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ candidate ] ); - _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 ); - - object.__webglMorphTargetInfluences[ m ] = candidateInfluence; - - used[ candidate ] = 1; - candidateInfluence = -1; - m ++; - } - } - - // load updated influences uniform - - if( material.program.uniforms.morphTargetInfluences !== null ) { - - _gl.uniform1fv( material.program.uniforms.morphTargetInfluences, object.__webglMorphTargetInfluences ); - - } - - } - - - function renderBufferImmediate( object, program, shading ) { - - if ( ! object.__webglVertexBuffer ) object.__webglVertexBuffer = _gl.createBuffer(); - if ( ! object.__webglNormalBuffer ) object.__webglNormalBuffer = _gl.createBuffer(); - - if ( object.hasPos ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglVertexBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW ); - _gl.enableVertexAttribArray( program.attributes.position ); - _gl.vertexAttribPointer( program.attributes.position, 3, _gl.FLOAT, false, 0, 0 ); - - } - - if ( object.hasNormal ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer ); - - if ( shading == THREE.FlatShading ) { - - var nx, ny, nz, - nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz, - normalArray, - i, il = object.count * 3; - - for( i = 0; i < il; i += 9 ) { - - normalArray = object.normalArray; - - nax = normalArray[ i ]; - nay = normalArray[ i + 1 ]; - naz = normalArray[ i + 2 ]; - - nbx = normalArray[ i + 3 ]; - nby = normalArray[ i + 4 ]; - nbz = normalArray[ i + 5 ]; - - ncx = normalArray[ i + 6 ]; - ncy = normalArray[ i + 7 ]; - ncz = normalArray[ i + 8 ]; - - nx = ( nax + nbx + ncx ) / 3; - ny = ( nay + nby + ncy ) / 3; - nz = ( naz + nbz + ncz ) / 3; - - normalArray[ i ] = nx; - normalArray[ i + 1 ] = ny; - normalArray[ i + 2 ] = nz; - - normalArray[ i + 3 ] = nx; - normalArray[ i + 4 ] = ny; - normalArray[ i + 5 ] = nz; - - normalArray[ i + 6 ] = nx; - normalArray[ i + 7 ] = ny; - normalArray[ i + 8 ] = nz; - - } - - } - - _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW ); - _gl.enableVertexAttribArray( program.attributes.normal ); - _gl.vertexAttribPointer( program.attributes.normal, 3, _gl.FLOAT, false, 0, 0 ); - - } - - _gl.drawArrays( _gl.TRIANGLES, 0, object.count ); - - object.count = 0; - - }; - - function setObjectFaces( object ) { - - if ( _oldDoubleSided != object.doubleSided ) { - - if( object.doubleSided ) { - - _gl.disable( _gl.CULL_FACE ); - - } else { - - _gl.enable( _gl.CULL_FACE ); - - } - - _oldDoubleSided = object.doubleSided; - - } - - if ( _oldFlipSided != object.flipSided ) { - - if( object.flipSided ) { - - _gl.frontFace( _gl.CW ); - - } else { - - _gl.frontFace( _gl.CCW ); - - } - - _oldFlipSided = object.flipSided; - - } - - }; - - function setDepthTest( test ) { - - if ( _oldDepth != test ) { - - if( test ) { - - _gl.enable( _gl.DEPTH_TEST ); - - } else { - - _gl.disable( _gl.DEPTH_TEST ); - - } - - _oldDepth = test; - - } - - }; - - function setPolygonOffset ( polygonoffset, factor, units ) { - - if ( _oldPolygonOffset != polygonoffset ) { - - if ( polygonoffset ) { - - _gl.enable( _gl.POLYGON_OFFSET_FILL ); - - } else { - - _gl.disable( _gl.POLYGON_OFFSET_FILL ); - - } - - _oldPolygonOffset = polygonoffset; - - } - - if ( polygonoffset && ( _oldPolygonOffsetFactor != factor || _oldPolygonOffsetUnits != units ) ) { - - _gl.polygonOffset( factor, units ); - - _oldPolygonOffsetFactor = factor; - _oldPolygonOffsetUnits = units; - - } - - }; - - function computeFrustum( m ) { - - _frustum[ 0 ].set( m.n41 - m.n11, m.n42 - m.n12, m.n43 - m.n13, m.n44 - m.n14 ); - _frustum[ 1 ].set( m.n41 + m.n11, m.n42 + m.n12, m.n43 + m.n13, m.n44 + m.n14 ); - _frustum[ 2 ].set( m.n41 + m.n21, m.n42 + m.n22, m.n43 + m.n23, m.n44 + m.n24 ); - _frustum[ 3 ].set( m.n41 - m.n21, m.n42 - m.n22, m.n43 - m.n23, m.n44 - m.n24 ); - _frustum[ 4 ].set( m.n41 - m.n31, m.n42 - m.n32, m.n43 - m.n33, m.n44 - m.n34 ); - _frustum[ 5 ].set( m.n41 + m.n31, m.n42 + m.n32, m.n43 + m.n33, m.n44 + m.n34 ); - - var i, plane; - - for ( i = 0; i < 6; i ++ ) { - - plane = _frustum[ i ]; - plane.divideScalar( Math.sqrt( plane.x * plane.x + plane.y * plane.y + plane.z * plane.z ) ); - - } - - }; - - function isInFrustum( object ) { - - var distance, matrix = object.matrixWorld, - radius = - object.geometry.boundingSphere.radius * Math.max( object.scale.x, Math.max( object.scale.y, object.scale.z ) ); - - for ( var i = 0; i < 6; i ++ ) { - - distance = _frustum[ i ].x * matrix.n14 + _frustum[ i ].y * matrix.n24 + _frustum[ i ].z * matrix.n34 + _frustum[ i ].w; - if ( distance <= radius ) return false; - - } - - return true; - - }; - - function addToFixedArray( where, what ) { - - where.list[ where.count ] = what; - where.count += 1; - - }; - - function unrollImmediateBufferMaterials( globject ) { - - var i, l, m, ml, material, - object = globject.object, - opaque = globject.opaque, - transparent = globject.transparent; - - transparent.count = 0; - opaque.count = 0; - - for ( m = 0, ml = object.materials.length; m < ml; m++ ) { - - material = object.materials[ m ]; - material.transparent ? addToFixedArray( transparent, material ) : addToFixedArray( opaque, material ); - - } - - }; - - function unrollBufferMaterials( globject ) { - - var i, l, m, ml, material, meshMaterial, - object = globject.object, - buffer = globject.buffer, - opaque = globject.opaque, - transparent = globject.transparent; - - transparent.count = 0; - opaque.count = 0; - - for ( m = 0, ml = object.materials.length; m < ml; m++ ) { - - meshMaterial = object.materials[ m ]; - - if ( meshMaterial instanceof THREE.MeshFaceMaterial ) { - - for ( i = 0, l = buffer.materials.length; i < l; i++ ) { - - material = buffer.materials[ i ]; - if ( material ) material.transparent ? addToFixedArray( transparent, material ) : addToFixedArray( opaque, material ); - - } - - } else { - - material = meshMaterial; - if ( material ) material.transparent ? addToFixedArray( transparent, material ) : addToFixedArray( opaque, material ); - - } - - } - - }; - - - function painterSort( a, b ) { - - return b.z - a.z; - - }; - - this.render = function( scene, camera, renderTarget, forceClear ) { - - var i, program, opaque, transparent, material, - o, ol, oil, webglObject, object, buffer, - lights = scene.lights, - fog = scene.fog; - - _this.data.vertices = 0; - _this.data.faces = 0; - _this.data.drawCalls = 0; - - camera.matrixAutoUpdate && camera.update( undefined, true ); - - scene.update( undefined, false, camera ); - - camera.matrixWorldInverse.flattenToArray( _viewMatrixArray ); - camera.projectionMatrix.flattenToArray( _projectionMatrixArray ); - - _projScreenMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse ); - computeFrustum( _projScreenMatrix ); - - this.initWebGLObjects( scene ); - - setRenderTarget( renderTarget ); - - if ( this.autoClear || forceClear ) { - - this.clear(); - - } - - // set matrices - - ol = scene.__webglObjects.length; - - for ( o = 0; o < ol; o++ ) { - - webglObject = scene.__webglObjects[ o ]; - object = webglObject.object; - - if ( object.visible ) { - - if ( ! ( object instanceof THREE.Mesh ) || isInFrustum( object ) ) { - - object.matrixWorld.flattenToArray( object._objectMatrixArray ); - - setupMatrices( object, camera ); - - unrollBufferMaterials( webglObject ); - - webglObject.render = true; - - if ( this.sortObjects ) { - - if ( webglObject.object.renderDepth ) { - - webglObject.z = webglObject.object.renderDepth; - - } else { - - _vector3.copy( object.position ); - _projScreenMatrix.multiplyVector3( _vector3 ); - - webglObject.z = _vector3.z; - - } - - } - - } else { - - webglObject.render = false; - - } - - } else { - - webglObject.render = false; - - } - - } - - if ( this.sortObjects ) { - - scene.__webglObjects.sort( painterSort ); - - } - - oil = scene.__webglObjectsImmediate.length; - - for ( o = 0; o < oil; o++ ) { - - webglObject = scene.__webglObjectsImmediate[ o ]; - object = webglObject.object; - - if ( object.visible ) { - - if( object.matrixAutoUpdate ) { - - object.matrixWorld.flattenToArray( object._objectMatrixArray ); - - } - - setupMatrices( object, camera ); - - unrollImmediateBufferMaterials( webglObject ); - - } - - } - - // opaque pass - - setBlending( THREE.NormalBlending ); - - for ( o = 0; o < ol; o ++ ) { - - webglObject = scene.__webglObjects[ o ]; - - if ( webglObject.render ) { - - object = webglObject.object; - buffer = webglObject.buffer; - opaque = webglObject.opaque; - - setObjectFaces( object ); - - for ( i = 0; i < opaque.count; i ++ ) { - - material = opaque.list[ i ]; - - setDepthTest( material.depthTest ); - setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); - renderBuffer( camera, lights, fog, material, buffer, object ); - - } - - } - - } - - // opaque pass (immediate simulator) - - for ( o = 0; o < oil; o++ ) { - - webglObject = scene.__webglObjectsImmediate[ o ]; - object = webglObject.object; - - if ( object.visible ) { - - opaque = webglObject.opaque; - - setObjectFaces( object ); - - for( i = 0; i < opaque.count; i++ ) { - - material = opaque.list[ i ]; - - setDepthTest( material.depthTest ); - setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); - - program = setProgram( camera, lights, fog, material, object ); - object.render( function( object ) { renderBufferImmediate( object, program, material.shading ); } ); - - } - - } - - } - - // transparent pass - - for ( o = 0; o < ol; o ++ ) { - - webglObject = scene.__webglObjects[ o ]; - - if ( webglObject.render ) { - - object = webglObject.object; - buffer = webglObject.buffer; - transparent = webglObject.transparent; - - setObjectFaces( object ); - - for ( i = 0; i < transparent.count; i ++ ) { - - material = transparent.list[ i ]; - - setBlending( material.blending ); - setDepthTest( material.depthTest ); - setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); - - renderBuffer( camera, lights, fog, material, buffer, object ); - - } - - } - - } - - // transparent pass (immediate simulator) - - for ( o = 0; o < oil; o++ ) { - - webglObject = scene.__webglObjectsImmediate[ o ]; - object = webglObject.object; - - if ( object.visible ) { - - transparent = webglObject.transparent; - - setObjectFaces( object ); - - for ( i = 0; i < transparent.count; i ++ ) { - - material = transparent.list[ i ]; - - setBlending( material.blending ); - setDepthTest( material.depthTest ); - setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); - - program = setProgram( camera, lights, fog, material, object ); - object.render( function( object ) { renderBufferImmediate( object, program, material.shading ); } ); - - } - - } - - } - - // render 2d - - if ( scene.__webglSprites.length ) { - - renderSprites( scene, camera ); - - } - - // render stencil shadows - - if ( _stencil && scene.__webglShadowVolumes.length && scene.lights.length ) { - - renderStencilShadows( scene ); - - } - - - // render lens flares - - if ( scene.__webglLensFlares.length ) { - - renderLensFlares( scene, camera ); - - } - - - // Generate mipmap if we're using any kind of mipmap filtering - - if ( renderTarget && renderTarget.minFilter !== THREE.NearestFilter && renderTarget.minFilter !== THREE.LinearFilter ) { - - updateRenderTargetMipmap( renderTarget ); - - } - - //_gl.finish(); - - }; - - - - /* - * Stencil Shadows - * method: we're rendering the world in light, then the shadow - * volumes into the stencil and last a big darkening - * quad over the whole thing. This is not how "you're - * supposed to" do stencil shadows but is much faster - * - */ - - function renderStencilShadows( scene ) { - - // setup stencil - - _gl.enable( _gl.POLYGON_OFFSET_FILL ); - _gl.polygonOffset( 0.1, 1.0 ); - _gl.enable( _gl.STENCIL_TEST ); - _gl.enable( _gl.DEPTH_TEST ); - _gl.depthMask( false ); - _gl.colorMask( false, false, false, false ); - - _gl.stencilFunc( _gl.ALWAYS, 1, 0xFF ); - _gl.stencilOpSeparate( _gl.BACK, _gl.KEEP, _gl.INCR, _gl.KEEP ); - _gl.stencilOpSeparate( _gl.FRONT, _gl.KEEP, _gl.DECR, _gl.KEEP ); - - - // loop through all directional lights - - var l, ll = scene.lights.length; - var p; - var light, lights = scene.lights; - var dirLight = []; - var object, geometryGroup, material; - var program; - var p_uniforms; - var m_uniforms; - var attributes; - var o, ol = scene.__webglShadowVolumes.length; - - for ( l = 0; l < ll; l++ ) { - - light = scene.lights[ l ]; - - if ( light instanceof THREE.DirectionalLight && light.castShadow ) { - - dirLight[ 0 ] = -light.position.x; - dirLight[ 1 ] = -light.position.y; - dirLight[ 2 ] = -light.position.z; - - // render all volumes - - for ( o = 0; o < ol; o++ ) { - - object = scene.__webglShadowVolumes[ o ].object; - geometryGroup = scene.__webglShadowVolumes[ o ].buffer; - material = object.materials[ 0 ]; - - if ( !material.program ) _this.initMaterial( material, lights, undefined, object ); - - program = material.program, - p_uniforms = program.uniforms, - m_uniforms = material.uniforms, - attributes = program.attributes; - - if ( _currentProgram !== program ) { - - _gl.useProgram( program ); - _currentProgram = program; - - _gl.uniformMatrix4fv( p_uniforms.projectionMatrix, false, _projectionMatrixArray ); - _gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, _viewMatrixArray ); - _gl.uniform3fv( p_uniforms.directionalLightDirection, dirLight ); - } - - - object.matrixWorld.flattenToArray( object._objectMatrixArray ); - _gl.uniformMatrix4fv( p_uniforms.objectMatrix, false, object._objectMatrixArray ); - - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer ); - _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 ); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer ); - _gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 ); - - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer ); - - _gl.cullFace( _gl.FRONT ); - _gl.drawElements( _gl.TRIANGLES, geometryGroup.__webglFaceCount, _gl.UNSIGNED_SHORT, 0 ); - - _gl.cullFace( _gl.BACK ); - _gl.drawElements( _gl.TRIANGLES, geometryGroup.__webglFaceCount, _gl.UNSIGNED_SHORT, 0 ); - - } - - } - - } - - - // setup color+stencil - - _gl.disable( _gl.POLYGON_OFFSET_FILL ); - _gl.colorMask( true, true, true, true ); - _gl.stencilFunc( _gl.NOTEQUAL, 0, 0xFF ); - _gl.stencilOp( _gl.KEEP, _gl.KEEP, _gl.KEEP ); - _gl.disable( _gl.DEPTH_TEST ); - - - // draw darkening polygon - - _oldBlending = -1; - _currentProgram = _stencilShadow.program; - - _gl.useProgram( _stencilShadow.program ); - _gl.uniformMatrix4fv( _stencilShadow.projectionLocation, false, _projectionMatrixArray ); - _gl.uniform1f( _stencilShadow.darknessLocation, _stencilShadow.darkness ); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, _stencilShadow.vertexBuffer ); - _gl.vertexAttribPointer( _stencilShadow.vertexLocation, 3, _gl.FLOAT, false, 0, 0 ); - _gl.enableVertexAttribArray( _stencilShadow.vertexLocation ); - - _gl.blendFunc( _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA ); - _gl.blendEquation( _gl.FUNC_ADD ); - - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _stencilShadow.elementBuffer ); - _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 ); - - - // disable stencil - - _gl.disable( _gl.STENCIL_TEST ); - _gl.enable( _gl.DEPTH_TEST ); - _gl.depthMask( _currentDepthMask ); - - } - - - /* - * Render sprites - * - */ - - function renderSprites( scene, camera ) { - - var o, ol, object; - var attributes = _sprite.attributes; - var uniforms = _sprite.uniforms; - var anyCustom = false; - var invAspect = _viewportHeight / _viewportWidth; - var size, scale = []; - var screenPosition; - var halfViewportWidth = _viewportWidth * 0.5; - var halfViewportHeight = _viewportHeight * 0.5; - var mergeWith3D = true; - - // setup gl - - _gl.useProgram( _sprite.program ); - _currentProgram = _sprite.program; - _oldBlending = -1; - - if ( !_spriteAttributesEnabled ) { - - _gl.enableVertexAttribArray( _sprite.attributes.position ); - _gl.enableVertexAttribArray( _sprite.attributes.uv ); - - _spriteAttributesEnabled = true; - - } - - _gl.disable( _gl.CULL_FACE ); - _gl.enable( _gl.BLEND ); - _gl.depthMask( true ); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, _sprite.vertexBuffer ); - _gl.vertexAttribPointer( attributes.position, 2, _gl.FLOAT, false, 2 * 8, 0 ); - _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 2 * 8, 8 ); - - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _sprite.elementBuffer ); - - _gl.uniformMatrix4fv( uniforms.projectionMatrix, false, _projectionMatrixArray ); - - _gl.activeTexture( _gl.TEXTURE0 ); - _gl.uniform1i( uniforms.map, 0 ); - - // update positions and sort - - for( o = 0, ol = scene.__webglSprites.length; o < ol; o++ ) { - - object = scene.__webglSprites[ o ]; - - if( !object.useScreenCoordinates ) { - - object._modelViewMatrix.multiplyToArray( camera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray ); - object.z = -object._modelViewMatrix.n34; - - } else { - - object.z = -object.position.z; - - } - - } - - scene.__webglSprites.sort( painterSort ); - - // render all non-custom shader sprites - - for ( o = 0, ol = scene.__webglSprites.length; o < ol; o++ ) { - - object = scene.__webglSprites[ o ]; - - if ( object.material === undefined ) { - - if ( object.map && object.map.image && object.map.image.width ) { - - if ( object.useScreenCoordinates ) { - - _gl.uniform1i( uniforms.useScreenCoordinates, 1 ); - _gl.uniform3f( uniforms.screenPosition, ( object.position.x - halfViewportWidth ) / halfViewportWidth, - ( halfViewportHeight - object.position.y ) / halfViewportHeight, - Math.max( 0, Math.min( 1, object.position.z ))); - - } else { - - - - _gl.uniform1i( uniforms.useScreenCoordinates, 0 ); - _gl.uniform1i( uniforms.affectedByDistance, object.affectedByDistance ? 1 : 0 ); - _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object._modelViewMatrixArray ); - - } - - size = object.map.image.width / ( object.scaleByViewport ? _viewportHeight : 1 ); - scale[ 0 ] = size * invAspect * object.scale.x; - scale[ 1 ] = size * object.scale.y; - - _gl.uniform2f( uniforms.uvScale, object.uvScale.x, object.uvScale.y ); - _gl.uniform2f( uniforms.uvOffset, object.uvOffset.x, object.uvOffset.y ); - _gl.uniform2f( uniforms.alignment, object.alignment.x, object.alignment.y ); - _gl.uniform1f( uniforms.opacity, object.opacity ); - _gl.uniform1f( uniforms.rotation, object.rotation ); - _gl.uniform2fv( uniforms.scale, scale ); - - if ( object.mergeWith3D && !mergeWith3D ) { - - _gl.enable( _gl.DEPTH_TEST ); - mergeWith3D = true; - - } else if ( !object.mergeWith3D && mergeWith3D ) { - - _gl.disable( _gl.DEPTH_TEST ); - mergeWith3D = false; - - } - - setBlending( object.blending ); - setTexture( object.map, 0 ); - - _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 ); - } - - } else { - - anyCustom = true; - - } - - } - - - // loop through all custom - - /* - if( anyCustom ) { - - } - */ - - // restore gl - - _gl.enable( _gl.CULL_FACE ); - _gl.enable( _gl.DEPTH_TEST ); - _gl.depthMask( _currentDepthMask ); - - } - - - - /* - * Render lens flares - * Method: renders 16x16 0xff00ff-colored points scattered over the light source area, - * reads these back and calculates occlusion. - * Then LensFlare.updateLensFlares() is called to re-position and - * update transparency of flares. Then they are rendered. - * - */ - - function renderLensFlares( scene, camera ) { - - var object, objectZ, geometryGroup, material; - var o, ol = scene.__webglLensFlares.length; - var f, fl, flare; - var tempPosition = new THREE.Vector3(); - var invAspect = _viewportHeight / _viewportWidth; - var halfViewportWidth = _viewportWidth * 0.5; - var halfViewportHeight = _viewportHeight * 0.5; - var size = 16 / _viewportHeight; - var scale = [ size * invAspect, size ]; - var screenPosition = [ 1, 1, 0 ]; - var screenPositionPixels = [ 1, 1 ]; - var sampleX, sampleY, readBackPixels = _lensFlare.readBackPixels; - var sampleMidX = 7 * 4; - var sampleMidY = 7 * 16 * 4; - var sampleIndex, visibility; - var uniforms = _lensFlare.uniforms; - var attributes = _lensFlare.attributes; - - - // set lensflare program and reset blending - - _gl.useProgram( _lensFlare.program ); - _currentProgram = _lensFlare.program; - _oldBlending = -1; - - - if ( ! _lensFlareAttributesEnabled ) { - - _gl.enableVertexAttribArray( _lensFlare.attributes.vertex ); - _gl.enableVertexAttribArray( _lensFlare.attributes.uv ); - - _lensFlareAttributesEnabled = true; - - } - - // loop through all lens flares to update their occlusion and positions - // setup gl and common used attribs/unforms - - _gl.uniform1i( uniforms.occlusionMap, 0 ); - _gl.uniform1i( uniforms.map, 1 ); - - _gl.bindBuffer( _gl.ARRAY_BUFFER, _lensFlare.vertexBuffer ); - _gl.vertexAttribPointer( attributes.vertex, 2, _gl.FLOAT, false, 2 * 8, 0 ); - _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 2 * 8, 8 ); - - - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.elementBuffer ); - - _gl.disable( _gl.CULL_FACE ); - _gl.depthMask( false ); - - _gl.activeTexture( _gl.TEXTURE0 ); - _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.occlusionTexture ); - - _gl.activeTexture( _gl.TEXTURE1 ); - - for ( o = 0; o < ol; o ++ ) { - - // calc object screen position - - object = scene.__webglLensFlares[ o ].object; - - tempPosition.set( object.matrixWorld.n14, object.matrixWorld.n24, object.matrixWorld.n34 ); - - camera.matrixWorldInverse.multiplyVector3( tempPosition ); - objectZ = tempPosition.z; - camera.projectionMatrix.multiplyVector3( tempPosition ); - - - // setup arrays for gl programs - - screenPosition[ 0 ] = tempPosition.x; - screenPosition[ 1 ] = tempPosition.y; - screenPosition[ 2 ] = tempPosition.z; - - screenPositionPixels[ 0 ] = screenPosition[ 0 ] * halfViewportWidth + halfViewportWidth; - screenPositionPixels[ 1 ] = screenPosition[ 1 ] * halfViewportHeight + halfViewportHeight; - - - // screen cull - - if ( _lensFlare.hasVertexTexture || ( screenPositionPixels[ 0 ] > 0 && - screenPositionPixels[ 0 ] < _viewportWidth && - screenPositionPixels[ 1 ] > 0 && - screenPositionPixels[ 1 ] < _viewportHeight )) { - - - // save current RGB to temp texture - - _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture ); - _gl.copyTexImage2D( _gl.TEXTURE_2D, 0, _gl.RGB, screenPositionPixels[ 0 ] - 8, screenPositionPixels[ 1 ] - 8, 16, 16, 0 ); - - - // render pink quad - - _gl.uniform1i( uniforms.renderType, 0 ); - _gl.uniform2fv( uniforms.scale, scale ); - _gl.uniform3fv( uniforms.screenPosition, screenPosition ); - - _gl.disable( _gl.BLEND ); - _gl.enable( _gl.DEPTH_TEST ); - - _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 ); - - - // copy result to occlusionMap - - _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.occlusionTexture ); - _gl.copyTexImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, screenPositionPixels[ 0 ] - 8, screenPositionPixels[ 1 ] - 8, 16, 16, 0 ); - - - // restore graphics - - _gl.uniform1i( uniforms.renderType, 1 ); - _gl.disable( _gl.DEPTH_TEST ); - _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture ); - _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 ); - - - // update object positions - - object.positionScreen.x = screenPosition[ 0 ]; - object.positionScreen.y = screenPosition[ 1 ]; - object.positionScreen.z = screenPosition[ 2 ]; - - if ( object.customUpdateCallback ) { - - object.customUpdateCallback( object ); - - } else { - - object.updateLensFlares(); - - } - - - // render flares - - _gl.uniform1i( uniforms.renderType, 2 ); - _gl.enable( _gl.BLEND ); - - for ( f = 0, fl = object.lensFlares.length; f < fl; f ++ ) { - - flare = object.lensFlares[ f ]; - - if ( flare.opacity > 0.001 && flare.scale > 0.001 ) { - - screenPosition[ 0 ] = flare.x; - screenPosition[ 1 ] = flare.y; - screenPosition[ 2 ] = flare.z; - - size = flare.size * flare.scale / _viewportHeight; - scale[ 0 ] = size * invAspect; - scale[ 1 ] = size; - - _gl.uniform3fv( uniforms.screenPosition, screenPosition ); - _gl.uniform2fv( uniforms.scale, scale ); - _gl.uniform1f( uniforms.rotation, flare.rotation ); - _gl.uniform1f( uniforms.opacity, flare.opacity ); - - setBlending( flare.blending ); - setTexture( flare.texture, 1 ); - - _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 ); - - } - - } - - } - - } - - // restore gl - - _gl.enable( _gl.CULL_FACE ); - _gl.enable( _gl.DEPTH_TEST ); - _gl.depthMask( _currentDepthMask ); - - }; - - - function setupMatrices( object, camera ) { - - object._modelViewMatrix.multiplyToArray( camera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray ); - THREE.Matrix4.makeInvert3x3( object._modelViewMatrix ).transposeIntoArray( object._normalMatrixArray ); - - }; - - this.initWebGLObjects = function ( scene ) { - - if ( !scene.__webglObjects ) { - - scene.__webglObjects = []; - scene.__webglObjectsImmediate = []; - scene.__webglShadowVolumes = []; - scene.__webglLensFlares = []; - scene.__webglSprites = []; - - } - - while ( scene.__objectsAdded.length ) { - - addObject( scene.__objectsAdded[ 0 ], scene ); - scene.__objectsAdded.splice( 0, 1 ); - - } - - while ( scene.__objectsRemoved.length ) { - - removeObject( scene.__objectsRemoved[ 0 ], scene ); - scene.__objectsRemoved.splice( 0, 1 ); - - } - - // update must be called after objects adding / removal - - for ( var o = 0, ol = scene.__webglObjects.length; o < ol; o ++ ) { - - updateObject( scene.__webglObjects[ o ].object, scene ); - - } - - for ( var o = 0, ol = scene.__webglShadowVolumes.length; o < ol; o ++ ) { - - updateObject( scene.__webglShadowVolumes[ o ].object, scene ); - - } - - for ( var o = 0, ol = scene.__webglLensFlares.length; o < ol; o ++ ) { - - updateObject( scene.__webglLensFlares[ o ].object, scene ); - - } - - /* - for ( var o = 0, ol = scene.__webglSprites.length; o < ol; o ++ ) { - - updateObject( scene.__webglSprites[ o ].object, scene ); - - } - */ - - }; - - function addObject( object, scene ) { - - var g, geometry, geometryGroup; - - if ( object._modelViewMatrix == undefined ) { - - object._modelViewMatrix = new THREE.Matrix4(); - - object._normalMatrixArray = new Float32Array( 9 ); - object._modelViewMatrixArray = new Float32Array( 16 ); - object._objectMatrixArray = new Float32Array( 16 ); - - object.matrixWorld.flattenToArray( object._objectMatrixArray ); - - } - - if ( object instanceof THREE.Mesh ) { - - geometry = object.geometry; - - if ( geometry.geometryGroups == undefined ) { - - sortFacesByMaterial( geometry ); - - } - - // create separate VBOs per geometry chunk - - for ( g in geometry.geometryGroups ) { - - geometryGroup = geometry.geometryGroups[ g ]; - - // initialise VBO on the first access - - if ( ! geometryGroup.__webglVertexBuffer ) { - - createMeshBuffers( geometryGroup ); - initMeshBuffers( geometryGroup, object ); - - geometry.__dirtyVertices = true; - geometry.__dirtyMorphTargets = true; - geometry.__dirtyElements = true; - geometry.__dirtyUvs = true; - geometry.__dirtyNormals = true; - geometry.__dirtyTangents = true; - geometry.__dirtyColors = true; - - } - - // create separate wrapper per each use of VBO - - if ( object instanceof THREE.ShadowVolume ) { - - addBuffer( scene.__webglShadowVolumes, geometryGroup, object ); - - } else { - - addBuffer( scene.__webglObjects, geometryGroup, object ); - - } - - } - - } else if ( object instanceof THREE.LensFlare ) { - - addBuffer( scene.__webglLensFlares, undefined, object ); - - } else if ( object instanceof THREE.Ribbon ) { - - geometry = object.geometry; - - if( ! geometry.__webglVertexBuffer ) { - - createRibbonBuffers( geometry ); - initRibbonBuffers( geometry ); - - geometry.__dirtyVertices = true; - geometry.__dirtyColors = true; - - } - - addBuffer( scene.__webglObjects, geometry, object ); - - } else if ( object instanceof THREE.Line ) { - - geometry = object.geometry; - - if( ! geometry.__webglVertexBuffer ) { - - createLineBuffers( geometry ); - initLineBuffers( geometry ); - - geometry.__dirtyVertices = true; - geometry.__dirtyColors = true; - - } - - addBuffer( scene.__webglObjects, geometry, object ); - - } else if ( object instanceof THREE.ParticleSystem ) { - - geometry = object.geometry; - - if ( ! geometry.__webglVertexBuffer ) { - - createParticleBuffers( geometry ); - initParticleBuffers( geometry ); - - geometry.__dirtyVertices = true; - geometry.__dirtyColors = true; - - } - - addBuffer( scene.__webglObjects, geometry, object ); - - } else if ( THREE.MarchingCubes !== undefined && object instanceof THREE.MarchingCubes ) { - - addBufferImmediate( scene.__webglObjectsImmediate, object ); - - } else if ( object instanceof THREE.Sprite ) { - - scene.__webglSprites.push( object ); - - } - - /*else if ( object instanceof THREE.Particle ) { - - }*/ - - }; - - function areCustomAttributesDirty( geometryGroup ) { - - var a, m, ml, material, materials; - - materials = geometryGroup.__materials; - - for ( m = 0, ml = materials.length; m < ml; m ++ ) { - - material = materials[ m ]; - - if ( material.attributes ) { - - for ( a in material.attributes ) { - - if ( material.attributes[ a ].needsUpdate ) return true; - - } - - } - - } - - - return false; - - }; - - function clearCustomAttributes( geometryGroup ) { - - var a, m, ml, material, materials; - - materials = geometryGroup.__materials; - - for ( m = 0, ml = materials.length; m < ml; m ++ ) { - - material = materials[ m ]; - - if ( material.attributes ) { - - for ( a in material.attributes ) { - - material.attributes[ a ].needsUpdate = false; - - } - - } - - } - - }; - - function updateObject( object, scene ) { - - var g, geometry, geometryGroup, a, customAttributeDirty; - - if ( object instanceof THREE.Mesh ) { - - geometry = object.geometry; - - // check all geometry groups - - for ( g in geometry.geometryGroups ) { - - geometryGroup = geometry.geometryGroups[ g ]; - - customAttributeDirty = areCustomAttributesDirty( geometryGroup ); - - if ( geometry.__dirtyVertices || geometry.__dirtyMorphTargets || geometry.__dirtyElements || - geometry.__dirtyUvs || geometry.__dirtyNormals || - geometry.__dirtyColors || geometry.__dirtyTangents || customAttributeDirty ) { - - setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW ); - - } - - } - - geometry.__dirtyVertices = false; - geometry.__dirtyMorphTargets = false; - geometry.__dirtyElements = false; - geometry.__dirtyUvs = false; - geometry.__dirtyNormals = false; - geometry.__dirtyTangents = false; - geometry.__dirtyColors = false; - - clearCustomAttributes( geometryGroup ); - - } else if ( object instanceof THREE.Ribbon ) { - - geometry = object.geometry; - - if( geometry.__dirtyVertices || geometry.__dirtyColors ) { - - setRibbonBuffers( geometry, _gl.DYNAMIC_DRAW ); - - } - - geometry.__dirtyVertices = false; - geometry.__dirtyColors = false; - - } else if ( object instanceof THREE.Line ) { - - geometry = object.geometry; - - if( geometry.__dirtyVertices || geometry.__dirtyColors ) { - - setLineBuffers( geometry, _gl.DYNAMIC_DRAW ); - - } - - geometry.__dirtyVertices = false; - geometry.__dirtyColors = false; - - } else if ( object instanceof THREE.ParticleSystem ) { - - geometry = object.geometry; - - if ( geometry.__dirtyVertices || geometry.__dirtyColors || object.sortParticles ) { - - setParticleBuffers( geometry, _gl.DYNAMIC_DRAW, object ); - - } - - geometry.__dirtyVertices = false; - geometry.__dirtyColors = false; - - }/* else if ( THREE.MarchingCubes !== undefined && object instanceof THREE.MarchingCubes ) { - - // it updates itself in render callback - - } else if ( object instanceof THREE.Particle ) { - - }*/ - - /* - delete geometry.vertices; - delete geometry.faces; - delete geometryGroup.faces; - */ - - }; - - function removeInstances( objlist, object ) { - - var o, ol; - - for ( o = objlist.length - 1; o >= 0; o -- ) { - - if ( objlist[ o ].object == object ) { - - objlist.splice( o, 1 ); - - } - - } - - }; - - function removeObject( object, scene ) { - - // must check as shadow volume before mesh (as they are also meshes) - - if ( object instanceof THREE.ShadowVolume ) { - - removeInstances( scene.__webglShadowVolumes, object ); - - } else if ( object instanceof THREE.Mesh || - object instanceof THREE.ParticleSystem || - object instanceof THREE.Ribbon || - object instanceof THREE.Line ) { - - removeInstances( scene.__webglObjects, object ); - - } else if ( object instanceof THREE.Sprite ) { - - removeInstances( scene.__webglSprites, object ); - - } else if ( object instanceof THREE.LensFlare ) { - - removeInstances( scene.__webglLensFlares, object ); - - } else if ( object instanceof THREE.MarchingCubes ) { - - removeInstances( scene.__webglObjectsImmediate, object ); - - } - - }; - - function sortFacesByMaterial( geometry ) { - - // TODO - // Should optimize by grouping faces with ColorFill / ColorStroke materials - // which could then use vertex color attributes instead of each being - // in its separate VBO - - var i, l, f, fl, face, material, materials, vertices, mhash, ghash, hash_map = {}; - var numMorphTargets = geometry.morphTargets !== undefined ? geometry.morphTargets.length : 0; - - geometry.geometryGroups = {}; - - function materialHash( material ) { - - var hash_array = []; - - for ( i = 0, l = material.length; i < l; i++ ) { - - if ( material[ i ] == undefined ) { - - hash_array.push( "undefined" ); - - } else { - - hash_array.push( material[ i ].id ); - - } - - } - - return hash_array.join( '_' ); - - } - - for ( f = 0, fl = geometry.faces.length; f < fl; f++ ) { - - face = geometry.faces[ f ]; - materials = face.materials; - - mhash = materialHash( materials ); - - if ( hash_map[ mhash ] == undefined ) { - - hash_map[ mhash ] = { 'hash': mhash, 'counter': 0 }; - - } - - ghash = hash_map[ mhash ].hash + '_' + hash_map[ mhash ].counter; - - if ( geometry.geometryGroups[ ghash ] == undefined ) { - - geometry.geometryGroups[ ghash ] = { 'faces': [], 'materials': materials, 'vertices': 0, 'numMorphTargets': numMorphTargets }; - - } - - vertices = face instanceof THREE.Face3 ? 3 : 4; - - if ( geometry.geometryGroups[ ghash ].vertices + vertices > 65535 ) { - - hash_map[ mhash ].counter += 1; - ghash = hash_map[ mhash ].hash + '_' + hash_map[ mhash ].counter; - - if ( geometry.geometryGroups[ ghash ] == undefined ) { - - geometry.geometryGroups[ ghash ] = { 'faces': [], 'materials': materials, 'vertices': 0, 'numMorphTargets': numMorphTargets }; - - } - - } - - geometry.geometryGroups[ ghash ].faces.push( f ); - geometry.geometryGroups[ ghash ].vertices += vertices; - - } - - }; - - function addBuffer( objlist, buffer, object ) { - - objlist.push( { - buffer: buffer, object: object, - opaque: { list: [], count: 0 }, - transparent: { list: [], count: 0 } - } ); - - }; - - function addBufferImmediate( objlist, object ) { - - objlist.push( { - object: object, - opaque: { list: [], count: 0 }, - transparent: { list: [], count: 0 } - } ); - - }; - - this.setFaceCulling = function ( cullFace, frontFace ) { - - if ( cullFace ) { - - if ( !frontFace || frontFace == "ccw" ) { - - _gl.frontFace( _gl.CCW ); - - } else { - - _gl.frontFace( _gl.CW ); - - } - - if( cullFace == "back" ) { - - _gl.cullFace( _gl.BACK ); - - } else if( cullFace == "front" ) { - - _gl.cullFace( _gl.FRONT ); - - } else { - - _gl.cullFace( _gl.FRONT_AND_BACK ); - - } - - _gl.enable( _gl.CULL_FACE ); - - } else { - - _gl.disable( _gl.CULL_FACE ); - - } - - }; - - this.supportsVertexTextures = function () { - - return _supportsVertexTextures; - - }; - - function maxVertexTextures() { - - return _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); - - }; - - function buildProgram( shaderID, fragmentShader, vertexShader, uniforms, attributes, parameters ) { - - var p, pl, program, code; - var chunks = []; - - // Generate code - - if ( shaderID ) { - - chunks.push( shaderID ); - - } else { - - chunks.push( fragmentShader ); - chunks.push( vertexShader ); - - } - - for ( p in parameters ) { - - chunks.push( p ); - chunks.push( parameters[ p ] ); - - } - - code = chunks.join(); - - // Check if code has been already compiled - - for ( p = 0, pl = _programs.length; p < pl; p ++ ) { - - if ( _programs[ p ].code == code ) { - - // console.log( "Code already compiled." /*: \n\n" + code*/ ); - - return _programs[ p ].program; - - } - - } - - //console.log( "building new program " ); - - // - - program = _gl.createProgram(); - - var prefix_fragment = [ - - "#ifdef GL_ES", - "precision highp float;", - "#endif", - - "#define MAX_DIR_LIGHTS " + parameters.maxDirLights, - "#define MAX_POINT_LIGHTS " + parameters.maxPointLights, - - parameters.fog ? "#define USE_FOG" : "", - parameters.fog instanceof THREE.FogExp2 ? "#define FOG_EXP2" : "", - - parameters.map ? "#define USE_MAP" : "", - parameters.envMap ? "#define USE_ENVMAP" : "", - parameters.lightMap ? "#define USE_LIGHTMAP" : "", - parameters.vertexColors ? "#define USE_COLOR" : "", - - "uniform mat4 viewMatrix;", - "uniform vec3 cameraPosition;", - "" - - ].join("\n"); - - var prefix_vertex = [ - - _supportsVertexTextures ? "#define VERTEX_TEXTURES" : "", - - "#define MAX_DIR_LIGHTS " + parameters.maxDirLights, - "#define MAX_POINT_LIGHTS " + parameters.maxPointLights, - - "#define MAX_BONES " + parameters.maxBones, - - parameters.map ? "#define USE_MAP" : "", - parameters.envMap ? "#define USE_ENVMAP" : "", - parameters.lightMap ? "#define USE_LIGHTMAP" : "", - parameters.vertexColors ? "#define USE_COLOR" : "", - parameters.skinning ? "#define USE_SKINNING" : "", - parameters.morphTargets ? "#define USE_MORPHTARGETS" : "", - - parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "", - - "uniform mat4 objectMatrix;", - "uniform mat4 modelViewMatrix;", - "uniform mat4 projectionMatrix;", - "uniform mat4 viewMatrix;", - "uniform mat3 normalMatrix;", - "uniform vec3 cameraPosition;", - - "uniform mat4 cameraInverseMatrix;", - - "attribute vec3 position;", - "attribute vec3 normal;", - "attribute vec2 uv;", - "attribute vec2 uv2;", - - "#ifdef USE_COLOR", - - "attribute vec3 color;", - - "#endif", - - "#ifdef USE_MORPHTARGETS", - - "attribute vec3 morphTarget0;", - "attribute vec3 morphTarget1;", - "attribute vec3 morphTarget2;", - "attribute vec3 morphTarget3;", - "attribute vec3 morphTarget4;", - "attribute vec3 morphTarget5;", - "attribute vec3 morphTarget6;", - "attribute vec3 morphTarget7;", - - "#endif", - - "#ifdef USE_SKINNING", - - "attribute vec4 skinVertexA;", - "attribute vec4 skinVertexB;", - "attribute vec4 skinIndex;", - "attribute vec4 skinWeight;", - - "#endif", - - "" - - ].join("\n"); - - _gl.attachShader( program, getShader( "fragment", prefix_fragment + fragmentShader ) ); - _gl.attachShader( program, getShader( "vertex", prefix_vertex + vertexShader ) ); - - _gl.linkProgram( program ); - - if ( !_gl.getProgramParameter( program, _gl.LINK_STATUS ) ) { - - console.error( "Could not initialise shader\n" + "VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" ); - - } - - //console.log( prefix_fragment + fragmentShader ); - //console.log( prefix_vertex + vertexShader ); - - program.uniforms = {}; - program.attributes = {}; - - var identifiers, u, a, i; - - // cache uniform locations - - identifiers = [ - - 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition', - 'cameraInverseMatrix', 'boneGlobalMatrices', 'morphTargetInfluences' - - ]; - - for ( u in uniforms ) { - - identifiers.push( u ); - - } - - cacheUniformLocations( program, identifiers ); - - // cache attributes locations - - identifiers = [ - - "position", "normal", "uv", "uv2", "tangent", "color", - "skinVertexA", "skinVertexB", "skinIndex", "skinWeight" - - ]; - - for ( i = 0; i < parameters.maxMorphTargets; i++ ) { - - identifiers.push( "morphTarget" + i ); - - } - - for ( a in attributes ) { - - identifiers.push( a ); - - } - - cacheAttributeLocations( program, identifiers ); - - _programs.push( { program: program, code: code } ); - - return program; - - }; - - function loadUniformsSkinning( uniforms, object ) { - - _gl.uniformMatrix4fv( uniforms.cameraInverseMatrix, false, _viewMatrixArray ); - _gl.uniformMatrix4fv( uniforms.boneGlobalMatrices, false, object.boneMatrices ); - - }; - - - function loadUniformsMatrices( uniforms, object ) { - - _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object._modelViewMatrixArray ); - _gl.uniformMatrix3fv( uniforms.normalMatrix, false, object._normalMatrixArray ); - - }; - - function loadUniformsGeneric( program, uniforms ) { - - var u, uniform, value, type, location, texture; - - for( u in uniforms ) { - - location = program.uniforms[u]; - if ( !location ) continue; - - uniform = uniforms[u]; - - type = uniform.type; - value = uniform.value; - - if( type == "i" ) { - - _gl.uniform1i( location, value ); - - } else if( type == "f" ) { - - _gl.uniform1f( location, value ); - - } else if( type == "fv1" ) { - - _gl.uniform1fv( location, value ); - - } else if( type == "fv" ) { - - _gl.uniform3fv( location, value ); - - } else if( type == "v2" ) { - - _gl.uniform2f( location, value.x, value.y ); - - } else if( type == "v3" ) { - - _gl.uniform3f( location, value.x, value.y, value.z ); - - } else if( type == "v4" ) { - - _gl.uniform4f( location, value.x, value.y, value.z, value.w ); - - } else if( type == "c" ) { - - _gl.uniform3f( location, value.r, value.g, value.b ); - - } else if( type == "t" ) { - - _gl.uniform1i( location, value ); - - texture = uniform.texture; - - if ( !texture ) continue; - - if ( texture.image instanceof Array && texture.image.length == 6 ) { - - setCubeTexture( texture, value ); - - } else { - - setTexture( texture, value ); - - } - - } - - } - - }; - - function setBlending( blending ) { - - if ( blending != _oldBlending ) { - - switch ( blending ) { - - case THREE.AdditiveBlending: - - _gl.blendEquation( _gl.FUNC_ADD ); - _gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE ); - - break; - - case THREE.SubtractiveBlending: - - // TODO: Find blendFuncSeparate() combination - - _gl.blendEquation( _gl.FUNC_ADD ); - _gl.blendFunc( _gl.ZERO, _gl.ONE_MINUS_SRC_COLOR ); - - break; - - case THREE.MultiplyBlending: - - // TODO: Find blendFuncSeparate() combination - - _gl.blendEquation( _gl.FUNC_ADD ); - _gl.blendFunc( _gl.ZERO, _gl.SRC_COLOR ); - - break; - - default: - - _gl.blendEquationSeparate( _gl.FUNC_ADD, _gl.FUNC_ADD ); - _gl.blendFuncSeparate( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA ); - - break; - - } - - _oldBlending = blending; - - } - - }; - - function setTextureParameters( textureType, texture, image ) { - - if ( isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ) ) { - - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) ); - - _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) ); - - _gl.generateMipmap( textureType ); - - } else { - - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE ); - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE ); - - _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) ); - - } - - }; - - function setTexture( texture, slot ) { - - if ( texture.needsUpdate ) { - - if ( !texture.__webglInit ) { - - texture.__webglTexture = _gl.createTexture(); - - _gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture ); - _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image ); - - texture.__webglInit = true; - - } else { - - _gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture ); - // _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image ); - _gl.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image ); - - } - - setTextureParameters( _gl.TEXTURE_2D, texture, texture.image ); - _gl.bindTexture( _gl.TEXTURE_2D, null ); - - texture.needsUpdate = false; - - } - - /* - if ( texture.needsUpdate ) { - - if ( texture.__webglTexture ) { - - texture.__webglTexture = _gl.deleteTexture( texture.__webglTexture ); - - } - - texture.__webglTexture = _gl.createTexture(); - - _gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture ); - _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image ); - - setTextureParameters( _gl.TEXTURE_2D, texture, texture.image ); - - _gl.bindTexture( _gl.TEXTURE_2D, null ); - - texture.needsUpdate = false; - - } - */ - - _gl.activeTexture( _gl.TEXTURE0 + slot ); - _gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture ); - - - }; - - function setCubeTexture( texture, slot ) { - - if ( texture.image.length == 6 ) { - - if ( texture.needsUpdate ) { - - if ( !texture.__webglInit ) { - - texture.image.__webglTextureCube = _gl.createTexture(); - - _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube ); - - for ( var i = 0; i < 6; ++i ) { - - _gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image[ i ] ); - - } - - texture.__webglInit = true; - - } else { - - _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube ); - - for ( var i = 0; i < 6; ++i ) { - - // _gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image[ i ] ); - _gl.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image[ i ] ); - - } - - } - - setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, texture.image[0] ); - _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null ); - - texture.needsUpdate = false; - - } - - _gl.activeTexture( _gl.TEXTURE0 + slot ); - _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube ); - - } - - }; - - function setRenderTarget( renderTexture ) { - - if ( renderTexture && !renderTexture.__webglFramebuffer ) { - - if( renderTexture.depthBuffer === undefined ) renderTexture.depthBuffer = true; - if( renderTexture.stencilBuffer === undefined ) renderTexture.stencilBuffer = true; - - renderTexture.__webglFramebuffer = _gl.createFramebuffer(); - renderTexture.__webglRenderbuffer = _gl.createRenderbuffer(); - renderTexture.__webglTexture = _gl.createTexture(); - - - // Setup texture - - _gl.bindTexture( _gl.TEXTURE_2D, renderTexture.__webglTexture ); - _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, paramThreeToGL( renderTexture.wrapS ) ); - _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, paramThreeToGL( renderTexture.wrapT ) ); - _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( renderTexture.magFilter ) ); - _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( renderTexture.minFilter ) ); - _gl.texImage2D( _gl.TEXTURE_2D, 0, paramThreeToGL( renderTexture.format ), renderTexture.width, renderTexture.height, 0, paramThreeToGL( renderTexture.format ), paramThreeToGL( renderTexture.type ), null ); - - // Setup render and frame buffer - - _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTexture.__webglRenderbuffer ); - _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTexture.__webglFramebuffer ); - - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, renderTexture.__webglTexture, 0 ); - - if ( renderTexture.depthBuffer && !renderTexture.stencilBuffer ) { - - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTexture.width, renderTexture.height ); - _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTexture.__webglRenderbuffer ); - - /* For some reason this is not working. Defaulting to RGBA4. - } else if( !renderTexture.depthBuffer && renderTexture.stencilBuffer ) { - - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTexture.width, renderTexture.height ); - _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTexture.__webglRenderbuffer ); - */ - } else if( renderTexture.depthBuffer && renderTexture.stencilBuffer ) { - - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTexture.width, renderTexture.height ); - _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTexture.__webglRenderbuffer ); - - } else { - - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTexture.width, renderTexture.height ); - - } - - - // Release everything - - _gl.bindTexture( _gl.TEXTURE_2D, null ); - _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); - _gl.bindFramebuffer( _gl.FRAMEBUFFER, null); - - } - - var framebuffer, width, height; - - if ( renderTexture ) { - - framebuffer = renderTexture.__webglFramebuffer; - width = renderTexture.width; - height = renderTexture.height; - - } else { - - framebuffer = null; - width = _viewportWidth; - height = _viewportHeight; - - } - - if ( framebuffer != _currentFramebuffer ) { - - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - _gl.viewport( _viewportX, _viewportY, width, height ); - - _currentFramebuffer = framebuffer; - - } - - }; - - function updateRenderTargetMipmap( renderTarget ) { - - _gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture ); - _gl.generateMipmap( _gl.TEXTURE_2D ); - _gl.bindTexture( _gl.TEXTURE_2D, null ); - - }; - - function cacheUniformLocations( program, identifiers ) { - - var i, l, id; - - for( i = 0, l = identifiers.length; i < l; i++ ) { - - id = identifiers[ i ]; - program.uniforms[ id ] = _gl.getUniformLocation( program, id ); - - } - - }; - - function cacheAttributeLocations( program, identifiers ) { - - var i, l, id; - - for( i = 0, l = identifiers.length; i < l; i++ ) { - - id = identifiers[ i ]; - program.attributes[ id ] = _gl.getAttribLocation( program, id ); - - } - - }; - - function getShader( type, string ) { - - var shader; - - if ( type == "fragment" ) { - - shader = _gl.createShader( _gl.FRAGMENT_SHADER ); - - } else if ( type == "vertex" ) { - - shader = _gl.createShader( _gl.VERTEX_SHADER ); - - } - - _gl.shaderSource( shader, string ); - _gl.compileShader( shader ); - - if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) { - - console.error( _gl.getShaderInfoLog( shader ) ); - console.error( string ); - return null; - - } - - return shader; - - }; - - // fallback filters for non-power-of-2 textures - - function filterFallback( f ) { - - switch ( f ) { - - case THREE.NearestFilter: - case THREE.NearestMipMapNearestFilter: - case THREE.NearestMipMapLinearFilter: return _gl.NEAREST; break; - - case THREE.LinearFilter: - case THREE.LinearMipMapNearestFilter: - case THREE.LinearMipMapLinearFilter: - default: - - return _gl.LINEAR; break; - - } - - }; - - function paramThreeToGL( p ) { - - switch ( p ) { - - case THREE.RepeatWrapping: return _gl.REPEAT; break; - case THREE.ClampToEdgeWrapping: return _gl.CLAMP_TO_EDGE; break; - case THREE.MirroredRepeatWrapping: return _gl.MIRRORED_REPEAT; break; - - case THREE.NearestFilter: return _gl.NEAREST; break; - case THREE.NearestMipMapNearestFilter: return _gl.NEAREST_MIPMAP_NEAREST; break; - case THREE.NearestMipMapLinearFilter: return _gl.NEAREST_MIPMAP_LINEAR; break; - - case THREE.LinearFilter: return _gl.LINEAR; break; - case THREE.LinearMipMapNearestFilter: return _gl.LINEAR_MIPMAP_NEAREST; break; - case THREE.LinearMipMapLinearFilter: return _gl.LINEAR_MIPMAP_LINEAR; break; - - case THREE.ByteType: return _gl.BYTE; break; - case THREE.UnsignedByteType: return _gl.UNSIGNED_BYTE; break; - case THREE.ShortType: return _gl.SHORT; break; - case THREE.UnsignedShortType: return _gl.UNSIGNED_SHORT; break; - case THREE.IntType: return _gl.INT; break; - case THREE.UnsignedShortType: return _gl.UNSIGNED_INT; break; - case THREE.FloatType: return _gl.FLOAT; break; - - case THREE.AlphaFormat: return _gl.ALPHA; break; - case THREE.RGBFormat: return _gl.RGB; break; - case THREE.RGBAFormat: return _gl.RGBA; break; - case THREE.LuminanceFormat: return _gl.LUMINANCE; break; - case THREE.LuminanceAlphaFormat: return _gl.LUMINANCE_ALPHA; break; - - } - - return 0; - - }; - - function isPowerOfTwo( value ) { - - return ( value & ( value - 1 ) ) == 0; - - }; - - function materialNeedsSmoothNormals( material ) { - - return material && material.shading != undefined && material.shading == THREE.SmoothShading; - - }; - - function bufferNeedsSmoothNormals( geometryGroup, object ) { - - var m, ml, i, l, meshMaterial, needsSmoothNormals = false; - - for ( m = 0, ml = object.materials.length; m < ml; m++ ) { - - meshMaterial = object.materials[ m ]; - - if ( meshMaterial instanceof THREE.MeshFaceMaterial ) { - - for ( i = 0, l = geometryGroup.materials.length; i < l; i++ ) { - - if ( materialNeedsSmoothNormals( geometryGroup.materials[ i ] ) ) { - - needsSmoothNormals = true; - break; - - } - - } - - } else { - - if ( materialNeedsSmoothNormals( meshMaterial ) ) { - - needsSmoothNormals = true; - break; - - } - - } - - if ( needsSmoothNormals ) break; - - } - - return needsSmoothNormals; - - }; - - function unrollGroupMaterials( geometryGroup, object ) { - - var m, ml, i, il, - material, meshMaterial, - materials = []; - - for ( m = 0, ml = object.materials.length; m < ml; m++ ) { - - meshMaterial = object.materials[ m ]; - - if ( meshMaterial instanceof THREE.MeshFaceMaterial ) { - - for ( i = 0, l = geometryGroup.materials.length; i < l; i++ ) { - - material = geometryGroup.materials[ i ]; - - if ( material ) { - - materials.push( material ); - - } - - } - - } else { - - material = meshMaterial; - - if ( material ) { - - materials.push( material ); - - } - - } - - } - - return materials; - - }; - - function bufferGuessVertexColorType( materials, geometryGroup, object ) { - - var i, m, ml = materials.length; - - // use vertexColor type from the first material in unrolled materials - - for ( i = 0; i < ml; i++ ) { - - m = materials[ i ]; - - if ( m.vertexColors ) { - - return m.vertexColors; - - } - - } - - return false; - - }; - - function bufferGuessNormalType( materials, geometryGroup, object ) { - - var i, m, ml = materials.length; - - // only MeshBasicMaterial and MeshDepthMaterial don't need normals - - for ( i = 0; i < ml; i++ ) { - - m = materials[ i ]; - - if ( ( m instanceof THREE.MeshBasicMaterial && !m.envMap ) || m instanceof THREE.MeshDepthMaterial ) continue; - - if ( materialNeedsSmoothNormals( m ) ) { - - return THREE.SmoothShading; - - } else { - - return THREE.FlatShading; - - } - - } - - return false; - - }; - - function bufferGuessUVType( materials, geometryGroup, object ) { - - var i, m, ml = materials.length; - - // material must use some texture to require uvs - - for ( i = 0; i < ml; i++ ) { - - m = materials[ i ]; - - if ( m.map || m.lightMap || m instanceof THREE.MeshShaderMaterial ) { - - return true; - - } - - } - - return false; - - }; - - function allocateBones( object ) { - - // default for when object is not specified - // ( for example when prebuilding shader - // to be used with multiple objects ) - // - // - leave some extra space for other uniforms - // - limit here is ANGLE's 254 max uniform vectors - // (up to 54 should be safe) - - var maxBones = 50; - - if ( object !== undefined && object instanceof THREE.SkinnedMesh ) { - - maxBones = object.bones.length; - - } - - return maxBones; - - }; - - function allocateLights( lights, maxLights ) { - - var l, ll, light, dirLights, pointLights, maxDirLights, maxPointLights; - dirLights = pointLights = maxDirLights = maxPointLights = 0; - - for ( l = 0, ll = lights.length; l < ll; l++ ) { - - light = lights[ l ]; - - if ( light instanceof THREE.DirectionalLight ) dirLights++; - if ( light instanceof THREE.PointLight ) pointLights++; - - } - - if ( ( pointLights + dirLights ) <= maxLights ) { - - maxDirLights = dirLights; - maxPointLights = pointLights; - - } else { - - maxDirLights = Math.ceil( maxLights * dirLights / ( pointLights + dirLights ) ); - maxPointLights = maxLights - maxDirLights; - - } - - return { 'directional' : maxDirLights, 'point' : maxPointLights }; - - }; - - /* DEBUG - function getGLParams() { - - var params = { - - 'MAX_VARYING_VECTORS': _gl.getParameter( _gl.MAX_VARYING_VECTORS ), - 'MAX_VERTEX_ATTRIBS': _gl.getParameter( _gl.MAX_VERTEX_ATTRIBS ), - - 'MAX_TEXTURE_IMAGE_UNITS': _gl.getParameter( _gl.MAX_TEXTURE_IMAGE_UNITS ), - 'MAX_VERTEX_TEXTURE_IMAGE_UNITS': _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ), - 'MAX_COMBINED_TEXTURE_IMAGE_UNITS' : _gl.getParameter( _gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ), - - 'MAX_VERTEX_UNIFORM_VECTORS': _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS ), - 'MAX_FRAGMENT_UNIFORM_VECTORS': _gl.getParameter( _gl.MAX_FRAGMENT_UNIFORM_VECTORS ) - } - - return params; - }; - - function dumpObject( obj ) { - - var p, str = ""; - for ( p in obj ) { - - str += p + ": " + obj[p] + "\n"; - - } - - return str; - } - */ -}; - -/** - * @author szimek / https://github.com/szimek/ - */ - -THREE.WebGLRenderTarget = function ( width, height, options ) { - - this.width = width; - this.height = height; - - options = options || {}; - - this.wrapS = options.wrapS !== undefined ? options.wrapS : THREE.ClampToEdgeWrapping; - this.wrapT = options.wrapT !== undefined ? options.wrapT : THREE.ClampToEdgeWrapping; - - this.magFilter = options.magFilter !== undefined ? options.magFilter : THREE.LinearFilter; - this.minFilter = options.minFilter !== undefined ? options.minFilter : THREE.LinearMipMapLinearFilter; - - this.offset = new THREE.Vector2( 0, 0 ); - this.repeat = new THREE.Vector2( 1, 1 ); - - this.format = options.format !== undefined ? options.format : THREE.RGBAFormat; - this.type = options.type !== undefined ? options.type : THREE.UnsignedByteType; - - this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; - this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true; - -}; -/** - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.SoundRenderer = function() { - - this.volume = 1; - this.domElement = document.createElement( "div" ); - this.domElement.id = "THREESound"; - - this.cameraPosition = new THREE.Vector3(); - this.soundPosition = new THREE.Vector3(); - - this.render = function ( scene, camera, callSceneUpdate ) { - - if ( callSceneUpdate ) { - - scene.update( undefined, false, camera ); - - } - - var sound; - var sounds = scene.sounds; - var s, l = sounds.length; - - for ( s = 0; s < l; s++ ) { - - sound = sounds[ s ]; - - this.soundPosition.set( - - sound.matrixWorld.n14, - sound.matrixWorld.n24, - sound.matrixWorld.n34 - - ); - - this.soundPosition.subSelf( camera.position ); - - if( sound.isPlaying && sound.isLoaded ) { - - if ( !sound.isAddedToDOM ) { - - sound.addToDOM( this.domElement ); - - } - - sound.calculateVolumeAndPan( this.soundPosition ); - - } - - } - - } - -} -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.RenderableVertex = function () { - - this.positionWorld = new THREE.Vector3(); - this.positionScreen = new THREE.Vector4(); - - this.visible = true; - -}; - -THREE.RenderableVertex.prototype.copy = function ( vertex ) { - - this.positionWorld.copy( vertex.positionWorld ); - this.positionScreen.copy( vertex.positionScreen ); - -} -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.RenderableFace3 = function () { - - this.v1 = new THREE.RenderableVertex(); - this.v2 = new THREE.RenderableVertex(); - this.v3 = new THREE.RenderableVertex(); - - this.centroidWorld = new THREE.Vector3(); - this.centroidScreen = new THREE.Vector3(); - - this.normalWorld = new THREE.Vector3(); - this.vertexNormalsWorld = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ]; - - this.meshMaterials = null; - this.faceMaterials = null; - this.overdraw = false; - this.uvs = [[]]; - - this.z = null; - -}; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.RenderableFace4 = function () { - - this.v1 = new THREE.RenderableVertex(); - this.v2 = new THREE.RenderableVertex(); - this.v3 = new THREE.RenderableVertex(); - this.v4 = new THREE.RenderableVertex(); - - this.centroidWorld = new THREE.Vector3(); - this.centroidScreen = new THREE.Vector3(); - - this.normalWorld = new THREE.Vector3(); - this.vertexNormalsWorld = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ]; - - this.meshMaterials = null; - this.faceMaterials = null; - this.overdraw = false; - this.uvs = [[]]; - - this.z = null; - -}; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.RenderableObject = function () { - - this.object = null; - this.z = null; - -}; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.RenderableParticle = function () { - - this.x = null; - this.y = null; - this.z = null; - - this.rotation = null; - this.scale = new THREE.Vector2(); - - this.materials = null; - -}; -/** - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.RenderableLine = function () { - - this.z = null; - - this.v1 = new THREE.RenderableVertex(); - this.v2 = new THREE.RenderableVertex(); - - this.materials = null; - -}; -/** - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.ColorUtils = { - - adjustHSV : function ( color, h, s, v ) { - - var hsv = THREE.ColorUtils.__hsv; - - THREE.ColorUtils.rgbToHsv( color, hsv ); - - hsv.h = THREE.ColorUtils.clamp( hsv.h + h, 0, 1 ); - hsv.s = THREE.ColorUtils.clamp( hsv.s + s, 0, 1 ); - hsv.v = THREE.ColorUtils.clamp( hsv.v + v, 0, 1 ); - - color.setHSV( hsv.h, hsv.s, hsv.v ); - - }, - - // based on MochiKit implementation by Bob Ippolito - - rgbToHsv : function ( color, hsv ) { - - var r = color.r; - var g = color.g; - var b = color.b; - - var max = Math.max( Math.max( r, g ), b ); - var min = Math.min( Math.min( r, g ), b ); - - var hue; - var saturation; - var value = max; - - if ( min == max ) { - - hue = 0; - saturation = 0; - - } else { - - var delta = ( max - min ); - saturation = delta / max; - - if ( r == max ) { - - hue = ( g - b ) / delta; - - } else if ( g == max ) { - - hue = 2 + ( ( b - r ) / delta ); - - } else { - - hue = 4 + ( ( r - g ) / delta ); - } - - hue /= 6; - - if ( hue < 0 ) { - - hue += 1; - - } - - if ( hue > 1 ) { - - hue -= 1; - - } - - } - - if ( hsv === undefined ) { - - hsv = { h: 0, s: 0, v: 0 }; - - } - - hsv.h = hue; - hsv.s = saturation; - hsv.v = value; - - return hsv; - - }, - - clamp: function ( x, a, b ) { - - return x < a ? a : ( x > b ? b : x ); - - } - -}; - -THREE.ColorUtils.__hsv = { h: 0, s: 0, v: 0 };var GeometryUtils = { - - merge: function ( geometry1, object2 /* mesh | geometry */ ) { - - var isMesh = object2 instanceof THREE.Mesh, - vertexOffset = geometry1.vertices.length, - uvPosition = geometry1.faceVertexUvs[ 0 ].length, - geometry2 = isMesh ? object2.geometry : object2, - vertices1 = geometry1.vertices, - vertices2 = geometry2.vertices, - faces1 = geometry1.faces, - faces2 = geometry2.faces, - uvs1 = geometry1.faceVertexUvs[ 0 ], - uvs2 = geometry2.faceVertexUvs[ 0 ]; - - isMesh && object2.matrixAutoUpdate && object2.updateMatrix(); - - for ( var i = 0, il = vertices2.length; i < il; i ++ ) { - - var vertex = vertices2[ i ]; - - var vertexCopy = new THREE.Vertex( vertex.position.clone() ); - - isMesh && object2.matrix.multiplyVector3( vertexCopy.position ); - - vertices1.push( vertexCopy ); - - } - - for ( i = 0, il = faces2.length; i < il; i ++ ) { - - var face = faces2[ i ], faceCopy, normal, color, - faceVertexNormals = face.vertexNormals, - faceVertexColors = face.vertexColors; - - if ( face instanceof THREE.Face3 ) { - - faceCopy = new THREE.Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset ); - - } else if ( face instanceof THREE.Face4 ) { - - faceCopy = new THREE.Face4( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset, face.d + vertexOffset ); - - } - - faceCopy.normal.copy( face.normal ); - - for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) { - - normal = faceVertexNormals[ j ]; - faceCopy.vertexNormals.push( normal.clone() ); - - } - - faceCopy.color.copy( face.color ); - - for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) { - - color = faceVertexColors[ j ]; - faceCopy.vertexColors.push( color.clone() ); - - } - - faceCopy.materials = face.materials.slice(); - - faceCopy.centroid.copy( face.centroid ); - - faces1.push( faceCopy ); - - } - - for ( i = 0, il = uvs2.length; i < il; i ++ ) { - - var uv = uvs2[ i ], uvCopy = []; - - for ( var j = 0, jl = uv.length; j < jl; j ++ ) { - - uvCopy.push( new THREE.UV( uv[ j ].u, uv[ j ].v ) ); - - } - - uvs1.push( uvCopy ); - - } - - } - -}; -/** - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.ImageUtils = { - - loadTexture: function ( path, mapping, callback ) { - - var image = new Image(), - texture = new THREE.Texture( image, mapping ); - - image.onload = function () { texture.needsUpdate = true; if ( callback ) callback( this ); }; - image.src = path; - - return texture; - - }, - - loadTextureCube: function ( array, mapping, callback ) { - - var i, l, - images = [], - texture = new THREE.Texture( images, mapping ); - - images.loadCount = 0; - - for ( i = 0, l = array.length; i < l; ++i ) { - - images[ i ] = new Image(); - images[ i ].onload = function () { - - images.loadCount += 1; - if ( images.loadCount == 6 ) texture.needsUpdate = true; - if ( callback ) callback( this ); - - }; - - images[ i ].src = array[ i ]; - - } - - return texture; - - } - -}; -/** - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.SceneUtils = { - - addMesh : function ( scene, geometry, scale, x, y, z, rx, ry, rz, material ) { - - var mesh = new THREE.Mesh( geometry, material ); - mesh.scale.x = mesh.scale.y = mesh.scale.z = scale; - mesh.position.x = x; - mesh.position.y = y; - mesh.position.z = z; - mesh.rotation.x = rx; - mesh.rotation.y = ry; - mesh.rotation.z = rz; - scene.addObject( mesh ); - - return mesh; - - }, - - addPanoramaCubeWebGL : function ( scene, size, textureCube ) { - - var shader = THREE.ShaderUtils.lib["cube"]; - shader.uniforms["tCube"].texture = textureCube; - - var material = new THREE.MeshShaderMaterial( { - - fragmentShader: shader.fragmentShader, - vertexShader: shader.vertexShader, - uniforms: shader.uniforms - - } ), - - mesh = new THREE.Mesh( new THREE.CubeGeometry( size, size, size, 1, 1, 1, null, true ), material ); - scene.addObject( mesh ); - - return mesh; - - }, - - addPanoramaCube : function( scene, size, images ) { - - var materials = [], mesh; - - materials.push( new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[ 0 ] ) } ) ); - materials.push( new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[ 1 ] ) } ) ); - materials.push( new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[ 2 ] ) } ) ); - materials.push( new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[ 3 ] ) } ) ); - materials.push( new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[ 4 ] ) } ) ); - materials.push( new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[ 5 ] ) } ) ); - - mesh = new THREE.Mesh( new THREE.Cube( size, size, size, 1, 1, materials, true ), new THREE.MeshFaceMaterial() ); - scene.addObject( mesh ); - - return mesh; - - }, - - addPanoramaCubePlanes : function ( scene, size, images ) { - - - var hsize = size / 2, plane = new THREE.Plane( size, size ), pi = Math.PI, pi2 = Math.PI / 2; - - THREE.SceneUtils.addMesh( scene, plane, 1, 0, 0, -hsize, 0, 0, 0, new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[5] ) } ) ); - THREE.SceneUtils.addMesh( scene, plane, 1, -hsize, 0, 0, 0, pi2, 0, new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[0] ) } ) ); - THREE.SceneUtils.addMesh( scene, plane, 1, hsize, 0, 0, 0, -pi2, 0, new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[1] ) } ) ); - THREE.SceneUtils.addMesh( scene, plane, 1, 0, hsize, 0, pi2, 0, pi, new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[2] ) } ) ); - THREE.SceneUtils.addMesh( scene, plane, 1, 0, -hsize, 0, -pi2, 0, pi, new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[3] ) } ) ); - - }, - - showHierarchy : function ( root, visible ) { - - THREE.SceneUtils.traverseHierarchy( root, function( node ) { node.visible = visible; } ); - - }, - - traverseHierarchy : function ( root, callback ) { - - var n, i, l = root.children.length; - - for ( i = 0; i < l; i ++ ) { - - n = root.children[ i ]; - - callback( n ); - - THREE.SceneUtils.traverseHierarchy( n, callback ); - - } - - } - -}; -/** - * @author alteredq / http://alteredqualia.com/ - * @author mr.doob / http://mrdoob.com/ - */ - -THREE.ShaderUtils = { - - lib: { - - /* ------------------------------------------------------------------------- - // Fresnel shader - // - based on Nvidia Cg tutorial - ------------------------------------------------------------------------- */ - - 'fresnel': { - - uniforms: { - - "mRefractionRatio": { type: "f", value: 1.02 }, - "mFresnelBias": { type: "f", value: 0.1 }, - "mFresnelPower": { type: "f", value: 2.0 }, - "mFresnelScale": { type: "f", value: 1.0 }, - "tCube": { type: "t", value: 1, texture: null } - - }, - - fragmentShader: [ - - "uniform samplerCube tCube;", - - "varying vec3 vReflect;", - "varying vec3 vRefract[3];", - "varying float vReflectionFactor;", - - "void main() {", - - "vec4 reflectedColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );", - "vec4 refractedColor = vec4( 1.0, 1.0, 1.0, 1.0 );", - - "refractedColor.r = textureCube( tCube, vec3( -vRefract[0].x, vRefract[0].yz ) ).r;", - "refractedColor.g = textureCube( tCube, vec3( -vRefract[1].x, vRefract[1].yz ) ).g;", - "refractedColor.b = textureCube( tCube, vec3( -vRefract[2].x, vRefract[2].yz ) ).b;", - "refractedColor.a = 1.0;", - - "gl_FragColor = mix( refractedColor, reflectedColor, clamp( vReflectionFactor, 0.0, 1.0 ) );", - - "}" - - ].join("\n"), - - vertexShader: [ - - "uniform float mRefractionRatio;", - "uniform float mFresnelBias;", - "uniform float mFresnelScale;", - "uniform float mFresnelPower;", - - "varying vec3 vReflect;", - "varying vec3 vRefract[3];", - "varying float vReflectionFactor;", - - "void main() {", - - "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", - "vec4 mPosition = objectMatrix * vec4( position, 1.0 );", - - "vec3 nWorld = normalize ( mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal );", - - "vec3 I = mPosition.xyz - cameraPosition;", - - "vReflect = reflect( I, nWorld );", - "vRefract[0] = refract( normalize( I ), nWorld, mRefractionRatio );", - "vRefract[1] = refract( normalize( I ), nWorld, mRefractionRatio * 0.99 );", - "vRefract[2] = refract( normalize( I ), nWorld, mRefractionRatio * 0.98 );", - "vReflectionFactor = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( I ), nWorld ), mFresnelPower );", - - "gl_Position = projectionMatrix * mvPosition;", - - "}" - - ].join("\n") - - }, - - /* ------------------------------------------------------------------------- - // Normal map shader - // - Blinn-Phong - // - normal + diffuse + specular + AO + displacement maps - // - 1 point and 1 directional lights - ------------------------------------------------------------------------- */ - - 'normal' : { - - uniforms: { - - "enableAO" : { type: "i", value: 0 }, - "enableDiffuse" : { type: "i", value: 0 }, - "enableSpecular": { type: "i", value: 0 }, - - "tDiffuse" : { type: "t", value: 0, texture: null }, - "tNormal" : { type: "t", value: 2, texture: null }, - "tSpecular" : { type: "t", value: 3, texture: null }, - "tAO" : { type: "t", value: 4, texture: null }, - - "uNormalScale": { type: "f", value: 1.0 }, - - "tDisplacement": { type: "t", value: 5, texture: null }, - "uDisplacementBias": { type: "f", value: -0.5 }, - "uDisplacementScale": { type: "f", value: 2.5 }, - - "uPointLightPos": { type: "v3", value: new THREE.Vector3() }, - "uPointLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) }, - - "uDirLightPos": { type: "v3", value: new THREE.Vector3() }, - "uDirLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) }, - - "uAmbientLightColor": { type: "c", value: new THREE.Color( 0x050505 ) }, - - "uDiffuseColor": { type: "c", value: new THREE.Color( 0xeeeeee ) }, - "uSpecularColor": { type: "c", value: new THREE.Color( 0x111111 ) }, - "uAmbientColor": { type: "c", value: new THREE.Color( 0x050505 ) }, - "uShininess": { type: "f", value: 30 } - - }, - - fragmentShader: [ - - "uniform vec3 uDirLightPos;", - - "uniform vec3 uAmbientLightColor;", - "uniform vec3 uDirLightColor;", - "uniform vec3 uPointLightColor;", - - "uniform vec3 uAmbientColor;", - "uniform vec3 uDiffuseColor;", - "uniform vec3 uSpecularColor;", - "uniform float uShininess;", - - "uniform bool enableDiffuse;", - "uniform bool enableSpecular;", - "uniform bool enableAO;", - - "uniform sampler2D tDiffuse;", - "uniform sampler2D tNormal;", - "uniform sampler2D tSpecular;", - "uniform sampler2D tAO;", - - "uniform float uNormalScale;", - - "varying vec3 vTangent;", - "varying vec3 vBinormal;", - "varying vec3 vNormal;", - "varying vec2 vUv;", - - "varying vec3 vPointLightVector;", - "varying vec3 vViewPosition;", - - "void main() {", - - "vec3 diffuseTex = vec3( 1.0, 1.0, 1.0 );", - "vec3 aoTex = vec3( 1.0, 1.0, 1.0 );", - "vec3 specularTex = vec3( 1.0, 1.0, 1.0 );", - - "vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;", - "normalTex.xy *= uNormalScale;", - "normalTex = normalize( normalTex );", - - "if( enableDiffuse )", - "diffuseTex = texture2D( tDiffuse, vUv ).xyz;", - - "if( enableAO )", - "aoTex = texture2D( tAO, vUv ).xyz;", - - "if( enableSpecular )", - "specularTex = texture2D( tSpecular, vUv ).xyz;", - - "mat3 tsb = mat3( vTangent, vBinormal, vNormal );", - "vec3 finalNormal = tsb * normalTex;", - - "vec3 normal = normalize( finalNormal );", - "vec3 viewPosition = normalize( vViewPosition );", - - // point light - - "vec4 pointDiffuse = vec4( 0.0, 0.0, 0.0, 0.0 );", - "vec4 pointSpecular = vec4( 0.0, 0.0, 0.0, 0.0 );", - - "vec3 pointVector = normalize( vPointLightVector );", - "vec3 pointHalfVector = normalize( vPointLightVector + vViewPosition );", - - "float pointDotNormalHalf = dot( normal, pointHalfVector );", - "float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );", - - "float pointSpecularWeight = 0.0;", - "if ( pointDotNormalHalf >= 0.0 )", - "pointSpecularWeight = specularTex.r * pow( pointDotNormalHalf, uShininess );", - - "pointDiffuse += vec4( uDiffuseColor, 1.0 ) * pointDiffuseWeight;", - "pointSpecular += vec4( uSpecularColor, 1.0 ) * pointSpecularWeight * pointDiffuseWeight;", - - // directional light - - "vec4 dirDiffuse = vec4( 0.0, 0.0, 0.0, 0.0 );", - "vec4 dirSpecular = vec4( 0.0, 0.0, 0.0, 0.0 );", - - "vec4 lDirection = viewMatrix * vec4( uDirLightPos, 0.0 );", - - "vec3 dirVector = normalize( lDirection.xyz );", - "vec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );", - - "float dirDotNormalHalf = dot( normal, dirHalfVector );", - "float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );", - - "float dirSpecularWeight = 0.0;", - "if ( dirDotNormalHalf >= 0.0 )", - "dirSpecularWeight = specularTex.r * pow( dirDotNormalHalf, uShininess );", - - "dirDiffuse += vec4( uDiffuseColor, 1.0 ) * dirDiffuseWeight;", - "dirSpecular += vec4( uSpecularColor, 1.0 ) * dirSpecularWeight * dirDiffuseWeight;", - - // all lights contribution summation - - "vec4 totalLight = vec4( uAmbientLightColor * uAmbientColor, 1.0 );", - "totalLight += vec4( uDirLightColor, 1.0 ) * ( dirDiffuse + dirSpecular );", - "totalLight += vec4( uPointLightColor, 1.0 ) * ( pointDiffuse + pointSpecular );", - - "gl_FragColor = vec4( totalLight.xyz * aoTex * diffuseTex, 1.0 );", - - "}" - - ].join("\n"), - - vertexShader: [ - - "attribute vec4 tangent;", - - "uniform vec3 uPointLightPos;", - - "#ifdef VERTEX_TEXTURES", - - "uniform sampler2D tDisplacement;", - "uniform float uDisplacementScale;", - "uniform float uDisplacementBias;", - - "#endif", - - "varying vec3 vTangent;", - "varying vec3 vBinormal;", - "varying vec3 vNormal;", - "varying vec2 vUv;", - - "varying vec3 vPointLightVector;", - "varying vec3 vViewPosition;", - - "void main() {", - - "vec4 mPosition = objectMatrix * vec4( position, 1.0 );", - "vViewPosition = cameraPosition - mPosition.xyz;", - - "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", - "vNormal = normalize( normalMatrix * normal );", - - // tangent and binormal vectors - - "vTangent = normalize( normalMatrix * tangent.xyz );", - - "vBinormal = cross( vNormal, vTangent ) * tangent.w;", - "vBinormal = normalize( vBinormal );", - - "vUv = uv;", - - // point light - - "vec4 lPosition = viewMatrix * vec4( uPointLightPos, 1.0 );", - "vPointLightVector = normalize( lPosition.xyz - mvPosition.xyz );", - - // displacement mapping - - "#ifdef VERTEX_TEXTURES", - - "vec3 dv = texture2D( tDisplacement, uv ).xyz;", - "float df = uDisplacementScale * dv.x + uDisplacementBias;", - "vec4 displacedPosition = vec4( vNormal.xyz * df, 0.0 ) + mvPosition;", - "gl_Position = projectionMatrix * displacedPosition;", - - "#else", - - "gl_Position = projectionMatrix * mvPosition;", - - "#endif", - - "}" - - ].join("\n") - - }, - - /* ------------------------------------------------------------------------- - // Cube map shader - ------------------------------------------------------------------------- */ - - 'cube': { - - uniforms: { "tCube": { type: "t", value: 1, texture: null } }, - - vertexShader: [ - - "varying vec3 vViewPosition;", - - "void main() {", - - "vec4 mPosition = objectMatrix * vec4( position, 1.0 );", - "vViewPosition = cameraPosition - mPosition.xyz;", - - "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", - - "}" - - ].join("\n"), - - fragmentShader: [ - - "uniform samplerCube tCube;", - - "varying vec3 vViewPosition;", - - "void main() {", - - "vec3 wPos = cameraPosition - vViewPosition;", - "gl_FragColor = textureCube( tCube, vec3( - wPos.x, wPos.yz ) );", - - "}" - - ].join("\n") - - }, - - /* ------------------------------------------------------------------------ - // Convolution shader - // - ported from o3d sample to WebGL / GLSL - // http://o3d.googlecode.com/svn/trunk/samples/convolution.html - ------------------------------------------------------------------------ */ - - 'convolution': { - - uniforms: { - - "tDiffuse" : { type: "t", value: 0, texture: null }, - "uImageIncrement" : { type: "v2", value: new THREE.Vector2( 0.001953125, 0.0 ) }, - "cKernel" : { type: "fv1", value: [] } - - }, - - vertexShader: [ - - "varying vec2 vUv;", - - "uniform vec2 uImageIncrement;", - //"#define KERNEL_SIZE 25.0", - - "void main(void) {", - - "vUv = uv - ((KERNEL_SIZE - 1.0) / 2.0) * uImageIncrement;", - "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", - - "}" - - ].join("\n"), - - fragmentShader: [ - - "varying vec2 vUv;", - - "uniform sampler2D tDiffuse;", - "uniform vec2 uImageIncrement;", - - //"#define KERNEL_SIZE 25", - "uniform float cKernel[KERNEL_SIZE];", - - "void main(void) {", - - "vec2 imageCoord = vUv;", - "vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );", - "for( int i=0; i kMaxKernelSize ) kernelSize = kMaxKernelSize; - halfWidth = ( kernelSize - 1 ) * 0.5 - - values = new Array( kernelSize ); - sum = 0.0; - for ( i = 0; i < kernelSize; ++i ) { - - values[ i ] = gauss( i - halfWidth, sigma ); - sum += values[ i ]; - - } - - // normalize the kernel - - for ( i = 0; i < kernelSize; ++i ) values[ i ] /= sum; - - return values; - - } - -}; -/** - * @author mikael emtinger / http://gomo.se/ - */ - -THREE.AnimationHandler = (function() { - - var playing = []; - var library = {}; - var that = {}; - - - //--- update --- - - that.update = function( deltaTimeMS ) { - - for( var i = 0; i < playing.length; i++ ) - playing[ i ].update( deltaTimeMS ); - - }; - - - //--- add --- - - that.addToUpdate = function( animation ) { - - if( playing.indexOf( animation ) === -1 ) - playing.push( animation ); - - }; - - - //--- remove --- - - that.removeFromUpdate = function( animation ) { - - var index = playing.indexOf( animation ); - - if( index !== -1 ) - playing.splice( index, 1 ); - - }; - - - //--- add --- - - that.add = function( data ) { - - if( library[ data.name ] !== undefined ) - console.log( "THREE.AnimationHandler.add: Warning! " + data.name + " already exists in library. Overwriting." ); - - library[ data.name ] = data; - initData( data ); - - }; - - - //--- get --- - - that.get = function( name ) { - - if( typeof name === "string" ) { - - if( library[ name ] ) { - - return library[ name ]; - - } else { - - console.log( "THREE.AnimationHandler.get: Couldn't find animation " + name ); - return null; - - } - - } else { - - // todo: add simple tween library - - } - - }; - - //--- parse --- - - that.parse = function( root ) { - - // setup hierarchy - - var hierarchy = []; - - if ( root instanceof THREE.SkinnedMesh ) { - - for( var b = 0; b < root.bones.length; b++ ) { - - hierarchy.push( root.bones[ b ] ); - - } - - } else { - - parseRecurseHierarchy( root, hierarchy ); - - } - - return hierarchy; - - }; - - var parseRecurseHierarchy = function( root, hierarchy ) { - - hierarchy.push( root ); - - for( var c = 0; c < root.children.length; c++ ) - parseRecurseHierarchy( root.children[ c ], hierarchy ); - - } - - - //--- init data --- - - var initData = function( data ) { - - if( data.initialized === true ) - return; - - - // loop through all keys - - for( var h = 0; h < data.hierarchy.length; h++ ) { - - for( var k = 0; k < data.hierarchy[ h ].keys.length; k++ ) { - - // remove minus times - - if( data.hierarchy[ h ].keys[ k ].time < 0 ) - data.hierarchy[ h ].keys[ k ].time = 0; - - - // create quaternions - - if( data.hierarchy[ h ].keys[ k ].rot !== undefined && - !( data.hierarchy[ h ].keys[ k ].rot instanceof THREE.Quaternion ) ) { - - var quat = data.hierarchy[ h ].keys[ k ].rot; - data.hierarchy[ h ].keys[ k ].rot = new THREE.Quaternion( quat[0], quat[1], quat[2], quat[3] ); - - } - } - - - // prepare morph target keys - - if( data.hierarchy[ h ].keys[ 0 ].morphTargets !== undefined ) { - - // get all used - - var usedMorphTargets = {}; - - for( var k = 0; k < data.hierarchy[ h ].keys.length; k++ ) { - - for( var m = 0; m < data.hierarchy[ h ].keys[ k ].morphTargets.length; m++ ) { - - var morphTargetName = data.hierarchy[ h ].keys[ k ].morphTargets[ m ]; - usedMorphTargets[ morphTargetName ] = -1; - } - - } - - data.hierarchy[ h ].usedMorphTargets = usedMorphTargets; - - - // set all used on all frames - - for( var k = 0; k < data.hierarchy[ h ].keys.length; k++ ) { - - var influences = {}; - - for( var morphTargetName in usedMorphTargets ) { - - for( var m = 0; m < data.hierarchy[ h ].keys[ k ].morphTargets.length; m++ ) { - - if( data.hierarchy[ h ].keys[ k ].morphTargets[ m ] === morphTargetName ) { - - influences[ morphTargetName ] = data.hierarchy[ h ].keys[ k ].morphTargetsInfluences[ m ]; - break; - } - - } - - if( m === data.hierarchy[ h ].keys[ k ].morphTargets.length ) { - - influences[ morphTargetName ] = 0; - } - - } - - data.hierarchy[ h ].keys[ k ].morphTargetsInfluences = influences; - } - - } - - - // remove all keys that are on the same time - - for( var k = 1; k < data.hierarchy[ h ].keys.length; k++ ) { - - if( data.hierarchy[ h ].keys[ k ].time === data.hierarchy[ h ].keys[ k - 1 ].time ) { - - data.hierarchy[ h ].keys.splice( k, 1 ); - k--; - - } - - } - - - // set index - - for( var k = 1; k < data.hierarchy[ h ].keys.length; k++ ) { - - data.hierarchy[ h ].keys[ k ].index = k; - - } - - } - - - // JIT - - var lengthInFrames = parseInt( data.length * data.fps, 10 ); - - data.JIT = {}; - data.JIT.hierarchy = []; - - for( var h = 0; h < data.hierarchy.length; h++ ) - data.JIT.hierarchy.push( new Array( lengthInFrames )); - - - // done - - data.initialized = true; - - }; - - - // interpolation types - - that.LINEAR = 0; - that.CATMULLROM = 1; - that.CATMULLROM_FORWARD = 2; - - return that; -}()); -/** - * @author mikael emtinger / http://gomo.se/ - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.Animation = function( root, data, interpolationType, JITCompile ) { - - this.root = root; - this.data = THREE.AnimationHandler.get( data ); - this.hierarchy = THREE.AnimationHandler.parse( root ); - this.currentTime = 0; - this.timeScale = 1; - this.isPlaying = false; - this.isPaused = true; - this.loop = true; - this.interpolationType = interpolationType !== undefined ? interpolationType : THREE.AnimationHandler.LINEAR; - this.JITCompile = JITCompile !== undefined ? JITCompile : true; - - this.points = []; - this.target = new THREE.Vector3(); - -}; - -// Play - -THREE.Animation.prototype.play = function( loop, startTimeMS ) { - - if( !this.isPlaying ) { - - this.isPlaying = true; - this.loop = loop !== undefined ? loop : true; - this.currentTime = startTimeMS !== undefined ? startTimeMS : 0; - - - // reset key cache - - var h, hl = this.hierarchy.length, - object; - - for ( h = 0; h < hl; h++ ) { - - object = this.hierarchy[ h ]; - - if ( this.interpolationType !== THREE.AnimationHandler.CATMULLROM_FORWARD ) { - - object.useQuaternion = true; - - } - - object.matrixAutoUpdate = true; - - if ( object.animationCache === undefined ) { - - object.animationCache = {}; - object.animationCache.prevKey = { pos: 0, rot: 0, scl: 0 }; - object.animationCache.nextKey = { pos: 0, rot: 0, scl: 0 }; - object.animationCache.originalMatrix = object instanceof THREE.Bone ? object.skinMatrix : object.matrix; - - } - - var prevKey = object.animationCache.prevKey; - var nextKey = object.animationCache.nextKey; - - prevKey.pos = this.data.hierarchy[ h ].keys[ 0 ]; - prevKey.rot = this.data.hierarchy[ h ].keys[ 0 ]; - prevKey.scl = this.data.hierarchy[ h ].keys[ 0 ]; - - nextKey.pos = this.getNextKeyWith( "pos", h, 1 ); - nextKey.rot = this.getNextKeyWith( "rot", h, 1 ); - nextKey.scl = this.getNextKeyWith( "scl", h, 1 ); - - } - - this.update( 0 ); - - } - - this.isPaused = false; - - THREE.AnimationHandler.addToUpdate( this ); - -}; - - - -// Pause - -THREE.Animation.prototype.pause = function() { - - if( this.isPaused ) { - - THREE.AnimationHandler.addToUpdate( this ); - - } else { - - THREE.AnimationHandler.removeFromUpdate( this ); - - } - - this.isPaused = !this.isPaused; - -}; - - -// Stop - -THREE.Animation.prototype.stop = function() { - - this.isPlaying = false; - this.isPaused = false; - THREE.AnimationHandler.removeFromUpdate( this ); - - - // reset JIT matrix and remove cache - - for ( var h = 0; h < this.hierarchy.length; h++ ) { - - if ( this.hierarchy[ h ].animationCache !== undefined ) { - - if( this.hierarchy[ h ] instanceof THREE.Bone ) { - - this.hierarchy[ h ].skinMatrix = this.hierarchy[ h ].animationCache.originalMatrix; - - } else { - - this.hierarchy[ h ].matrix = this.hierarchy[ h ].animationCache.originalMatrix; - - } - - - delete this.hierarchy[ h ].animationCache; - - } - - } - -}; - - -// Update - -THREE.Animation.prototype.update = function( deltaTimeMS ) { - - // early out - - if( !this.isPlaying ) return; - - - // vars - - var types = [ "pos", "rot", "scl" ]; - var type; - var scale; - var vector; - var prevXYZ, nextXYZ; - var prevKey, nextKey; - var object; - var animationCache; - var frame; - var JIThierarchy = this.data.JIT.hierarchy; - var currentTime, unloopedCurrentTime; - var currentPoint, forwardPoint, angle; - - - // update - - this.currentTime += deltaTimeMS * this.timeScale; - - unloopedCurrentTime = this.currentTime; - currentTime = this.currentTime = this.currentTime % this.data.length; - frame = parseInt( Math.min( currentTime * this.data.fps, this.data.length * this.data.fps ), 10 ); - - - // update - - for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) { - - object = this.hierarchy[ h ]; - animationCache = object.animationCache; - - // use JIT? - - if ( this.JITCompile && JIThierarchy[ h ][ frame ] !== undefined ) { - - if( object instanceof THREE.Bone ) { - - object.skinMatrix = JIThierarchy[ h ][ frame ]; - - object.matrixAutoUpdate = false; - object.matrixWorldNeedsUpdate = false; - - } else { - - object.matrix = JIThierarchy[ h ][ frame ]; - - object.matrixAutoUpdate = false; - object.matrixWorldNeedsUpdate = true; - - } - - // use interpolation - - } else { - - // make sure so original matrix and not JIT matrix is set - - if ( this.JITCompile ) { - - if( object instanceof THREE.Bone ) { - - object.skinMatrix = object.animationCache.originalMatrix; - - } else { - - object.matrix = object.animationCache.originalMatrix; - - } - - } - - - // loop through pos/rot/scl - - for ( var t = 0; t < 3; t++ ) { - - // get keys - - type = types[ t ]; - prevKey = animationCache.prevKey[ type ]; - nextKey = animationCache.nextKey[ type ]; - - // switch keys? - - if ( nextKey.time <= unloopedCurrentTime ) { - - // did we loop? - - if ( currentTime < unloopedCurrentTime ) { - - if ( this.loop ) { - - prevKey = this.data.hierarchy[ h ].keys[ 0 ]; - nextKey = this.getNextKeyWith( type, h, 1 ); - - while( nextKey.time < currentTime ) { - - prevKey = nextKey; - nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 ); - - } - - } else { - - this.stop(); - return; - - } - - } else { - - do { - - prevKey = nextKey; - nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 ); - - } while( nextKey.time < currentTime ) - - } - - animationCache.prevKey[ type ] = prevKey; - animationCache.nextKey[ type ] = nextKey; - - } - - - object.matrixAutoUpdate = true; - object.matrixWorldNeedsUpdate = true; - - scale = ( currentTime - prevKey.time ) / ( nextKey.time - prevKey.time ); - prevXYZ = prevKey[ type ]; - nextXYZ = nextKey[ type ]; - - - // check scale error - - if ( scale < 0 || scale > 1 ) { - - console.log( "THREE.Animation.update: Warning! Scale out of bounds:" + scale + " on bone " + h ); - scale = scale < 0 ? 0 : 1; - - } - - // interpolate - - if ( type === "pos" ) { - - vector = object.position; - - if( this.interpolationType === THREE.AnimationHandler.LINEAR ) { - - vector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale; - vector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale; - vector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale; - - } else if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM || - this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) { - - this.points[ 0 ] = this.getPrevKeyWith( "pos", h, prevKey.index - 1 )[ "pos" ]; - this.points[ 1 ] = prevXYZ; - this.points[ 2 ] = nextXYZ; - this.points[ 3 ] = this.getNextKeyWith( "pos", h, nextKey.index + 1 )[ "pos" ]; - - scale = scale * 0.33 + 0.33; - - currentPoint = this.interpolateCatmullRom( this.points, scale ); - - vector.x = currentPoint[ 0 ]; - vector.y = currentPoint[ 1 ]; - vector.z = currentPoint[ 2 ]; - - if( this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) { - - forwardPoint = this.interpolateCatmullRom( this.points, scale * 1.01 ); - - this.target.set( forwardPoint[ 0 ], forwardPoint[ 1 ], forwardPoint[ 2 ] ); - this.target.subSelf( vector ); - this.target.y = 0; - this.target.normalize(); - - angle = Math.atan2( this.target.x, this.target.z ); - object.rotation.set( 0, angle, 0 ); - - } - - } - - } else if ( type === "rot" ) { - - THREE.Quaternion.slerp( prevXYZ, nextXYZ, object.quaternion, scale ); - - } else if( type === "scl" ) { - - vector = object.scale; - - vector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale; - vector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale; - vector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale; - - } - - } - - } - - } - - // update JIT? - - if ( this.JITCompile ) { - - if ( JIThierarchy[ 0 ][ frame ] === undefined ) { - - this.hierarchy[ 0 ].update( undefined, true ); - - for ( var h = 0; h < this.hierarchy.length; h++ ) { - - if( this.hierarchy[ h ] instanceof THREE.Bone ) { - - JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].skinMatrix.clone(); - - } else { - - JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].matrix.clone(); - - } - - } - - } - - } - -}; - -// Catmull-Rom spline - -THREE.Animation.prototype.interpolateCatmullRom = function ( points, scale ) { - - var c = [], v3 = [], - point, intPoint, weight, w2, w3, - pa, pb, pc, pd; - - point = ( points.length - 1 ) * scale; - intPoint = Math.floor( point ); - weight = point - intPoint; - - c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1; - c[ 1 ] = intPoint; - c[ 2 ] = intPoint > points.length - 2 ? intPoint : intPoint + 1; - c[ 3 ] = intPoint > points.length - 3 ? intPoint : intPoint + 2; - - pa = points[ c[ 0 ] ]; - pb = points[ c[ 1 ] ]; - pc = points[ c[ 2 ] ]; - pd = points[ c[ 3 ] ]; - - w2 = weight * weight; - w3 = weight * w2; - - v3[ 0 ] = this.interpolate( pa[ 0 ], pb[ 0 ], pc[ 0 ], pd[ 0 ], weight, w2, w3 ); - v3[ 1 ] = this.interpolate( pa[ 1 ], pb[ 1 ], pc[ 1 ], pd[ 1 ], weight, w2, w3 ); - v3[ 2 ] = this.interpolate( pa[ 2 ], pb[ 2 ], pc[ 2 ], pd[ 2 ], weight, w2, w3 ); - - return v3; - -}; - -THREE.Animation.prototype.interpolate = function( p0, p1, p2, p3, t, t2, t3 ) { - - var v0 = ( p2 - p0 ) * 0.5, - v1 = ( p3 - p1 ) * 0.5; - - return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1; - -}; - - - -// Get next key with - -THREE.Animation.prototype.getNextKeyWith = function( type, h, key ) { - - var keys = this.data.hierarchy[ h ].keys; - - if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM || - this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) { - - key = key < keys.length - 1 ? key : keys.length - 1; - - } else { - - key = key % keys.length; - - } - - for ( ; key < keys.length; key++ ) { - - if ( keys[ key ][ type ] !== undefined ) { - - return keys[ key ]; - - } - - } - - return this.data.hierarchy[ h ].keys[ 0 ]; - -}; - -// Get previous key with - -THREE.Animation.prototype.getPrevKeyWith = function( type, h, key ) { - - var keys = this.data.hierarchy[ h ].keys; - - if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM || - this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) { - - key = key > 0 ? key : 0; - - } else { - - key = key >= 0 ? key : key + keys.length; - - } - - - for ( ; key >= 0; key-- ) { - - if ( keys[ key ][ type ] !== undefined ) { - - return keys[ key ]; - - } - - } - - return this.data.hierarchy[ h ].keys[ keys.length - 1 ]; - -}; -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author paulirish / http://paulirish.com/ - * - * parameters = { - * fov: , - * aspect: , - * near: , - * far: , - * target: , - - * movementSpeed: , - * lookSpeed: , - - * noFly: , - * lookVertical: , - * autoForward: , - - * constrainVertical: , - * verticalMin: , - * verticalMax: , - - * heightSpeed: , - * heightCoef: , - * heightMin: , - * heightMax: , - - * domElement: , - * } - */ - -THREE.FPCamera = function ( parameters ) { - - THREE.Camera.call( this, parameters.fov, parameters.aspect, parameters.near, parameters.far, parameters.target ); - - this.movementSpeed = 1.0; - this.lookSpeed = 0.005; - - this.noFly = false; - this.lookVertical = true; - this.autoForward = false; - - this.activeLook = true; - - this.heightSpeed = false; - this.heightCoef = 1.0; - this.heightMin = 0.0; - - this.constrainVertical = false; - this.verticalMin = 0; - this.verticalMax = 3.14; - - this.domElement = document; - - this.lastUpdate = new Date().getTime(); - this.tdiff = 0; - - if ( parameters ) { - - if ( parameters.movementSpeed !== undefined ) this.movementSpeed = parameters.movementSpeed; - if ( parameters.lookSpeed !== undefined ) this.lookSpeed = parameters.lookSpeed; - if ( parameters.noFly !== undefined ) this.noFly = parameters.noFly; - if ( parameters.lookVertical !== undefined ) this.lookVertical = parameters.lookVertical; - - if ( parameters.autoForward !== undefined ) this.autoForward = parameters.autoForward; - - if ( parameters.activeLook !== undefined ) this.activeLook = parameters.activeLook; - - if ( parameters.heightSpeed !== undefined ) this.heightSpeed = parameters.heightSpeed; - if ( parameters.heightCoef !== undefined ) this.heightCoef = parameters.heightCoef; - if ( parameters.heightMin !== undefined ) this.heightMin = parameters.heightMin; - if ( parameters.heightMax !== undefined ) this.heightMax = parameters.heightMax; - - if ( parameters.constrainVertical !== undefined ) this.constrainVertical = parameters.constrainVertical; - if ( parameters.verticalMin !== undefined ) this.verticalMin = parameters.verticalMin; - if ( parameters.verticalMax !== undefined ) this.verticalMax = parameters.verticalMax; - - if ( parameters.domElement !== undefined ) this.domElement = parameters.domElement; - - } - - this.autoSpeedFactor = 0.0; - - this.mouseX = 0; - this.mouseY = 0; - - this.lat = 0; - this.lon = 0; - this.phi = 0; - this.theta = 0; - - this.moveForward = false; - this.moveBackward = false; - this.moveLeft = false; - this.moveRight = false; - this.freeze = false; - - this.mouseDragOn = false; - - this.windowHalfX = window.innerWidth / 2; - this.windowHalfY = window.innerHeight / 2; - - this.onMouseDown = function ( event ) { - - event.preventDefault(); - event.stopPropagation(); - - if ( this.activeLook ) { - - switch ( event.button ) { - - case 0: this.moveForward = true; break; - case 2: this.moveBackward = true; break; - - } - - } - - this.mouseDragOn = true; - - }; - - this.onMouseUp = function ( event ) { - - event.preventDefault(); - event.stopPropagation(); - - if ( this.activeLook ) { - - switch ( event.button ) { - - case 0: this.moveForward = false; break; - case 2: this.moveBackward = false; break; - - } - - } - - this.mouseDragOn = false; - - }; - - this.onMouseMove = function ( event ) { - - this.mouseX = event.clientX - this.windowHalfX; - this.mouseY = event.clientY - this.windowHalfY; - - }; - - this.onKeyDown = function ( event ) { - - switch( event.keyCode ) { - - case 38: /*up*/ - case 87: /*W*/ this.moveForward = true; break; - - case 37: /*left*/ - case 65: /*A*/ this.moveLeft = true; break; - - case 40: /*down*/ - case 83: /*S*/ this.moveBackward = true; break; - - case 39: /*right*/ - case 68: /*D*/ this.moveRight = true; break; - - case 81: this.freeze = !this.freeze; break; - - } - - }; - - this.onKeyUp = function ( event ) { - - switch( event.keyCode ) { - - case 38: /*up*/ - case 87: /*W*/ this.moveForward = false; break; - - case 37: /*left*/ - case 65: /*A*/ this.moveLeft = false; break; - - case 40: /*down*/ - case 83: /*S*/ this.moveBackward = false; break; - - case 39: /*right*/ - case 68: /*D*/ this.moveRight = false; break; - - } - - }; - - this.update = function() { - - var now = new Date().getTime(); - this.tdiff = ( now - this.lastUpdate ) / 1000; - this.lastUpdate = now; - - if ( !this.freeze ) { - - - if ( this.heightSpeed ) { - - var y = clamp( this.position.y, this.heightMin, this.heightMax ), - delta = y - this.heightMin; - - this.autoSpeedFactor = this.tdiff * ( delta * this.heightCoef ); - - } else { - - this.autoSpeedFactor = 0.0; - - } - - var actualMoveSpeed = this.tdiff * this.movementSpeed; - - if ( this.moveForward || ( this.autoForward && !this.moveBackward ) ) this.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) ); - if ( this.moveBackward ) this.translateZ( actualMoveSpeed ); - if ( this.moveLeft ) this.translateX( - actualMoveSpeed ); - if ( this.moveRight ) this.translateX( actualMoveSpeed ); - - var actualLookSpeed = this.tdiff * this.lookSpeed; - - if ( !this.activeLook ) { - - actualLookSpeed = 0; - - } - - this.lon += this.mouseX * actualLookSpeed; - if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed; - - this.lat = Math.max( - 85, Math.min( 85, this.lat ) ); - this.phi = ( 90 - this.lat ) * Math.PI / 180; - this.theta = this.lon * Math.PI / 180; - - var targetPosition = this.target.position, - position = this.position; - - targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta ); - targetPosition.y = position.y + 100 * Math.cos( this.phi ); - targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta ); - - } - - this.lon += this.mouseX * actualLookSpeed; - if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed; - - this.lat = Math.max( - 85, Math.min( 85, this.lat ) ); - this.phi = ( 90 - this.lat ) * Math.PI / 180; - this.theta = this.lon * Math.PI / 180; - - if ( this.constrainVertical ) { - - this.phi = map_linear( this.phi, 0, 3.14, this.verticalMin, this.verticalMax ); - - } - - var targetPosition = this.target.position, - position = this.position; - - targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta ); - targetPosition.y = position.y + 100 * Math.cos( this.phi ); - targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta ); - - this.supr.update.call( this ); - - }; - - - this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); - - this.domElement.addEventListener( 'mousemove', bind( this, this.onMouseMove ), false ); - this.domElement.addEventListener( 'mousedown', bind( this, this.onMouseDown ), false ); - this.domElement.addEventListener( 'mouseup', bind( this, this.onMouseUp ), false ); - this.domElement.addEventListener( 'keydown', bind( this, this.onKeyDown ), false ); - this.domElement.addEventListener( 'keyup', bind( this, this.onKeyUp ), false ); - - function bind( scope, fn ) { - - return function () { - - fn.apply( scope, arguments ); - - }; - - }; - - function map_linear( x, sa, sb, ea, eb ) { - - return ( x - sa ) * ( eb - ea ) / ( sb - sa ) + ea; - - }; - - function clamp_bottom( x, a ) { - - return x < a ? a : x; - - }; - - function clamp( x, a, b ) { - - return x < a ? a : ( x > b ? b : x ); - - }; - -}; - - -THREE.FPCamera.prototype = new THREE.Camera(); -THREE.FPCamera.prototype.constructor = THREE.FPCamera; -THREE.FPCamera.prototype.supr = THREE.Camera.prototype; - - -THREE.FPCamera.prototype.translate = function ( distance, axis ) { - - this.matrix.rotateAxis( axis ); - - if ( this.noFly ) { - - axis.y = 0; - - } - - this.position.addSelf( axis.multiplyScalar( distance ) ); - this.target.position.addSelf( axis.multiplyScalar( distance ) ); - -}; -/** - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * fov: , - * aspect: , - * near: , - * far: , - * target: , - - * waypoints: , // [ [x,y,z], [x,y,z] ... ] - * duration: , // seconds - - * useConstantSpeed: , - * resamplingCoef: , - - * createDebugPath: , - * createDebugDummy: , - - * lookSpeed: , - * lookVertical: , - * lookHorizontal: , - * verticalAngleMap: { srcRange: [ , ], dstRange: [ , ] } - * horizontalAngleMap: { srcRange: [ , ], dstRange: [ , ] } - - * domElement: , - * } - */ - -THREE.PathCamera = function ( parameters ) { - - THREE.Camera.call( this, parameters.fov, parameters.aspect, parameters.near, parameters.far, parameters.target ); - - this.id = "PathCamera" + THREE.PathCameraIdCounter ++; - - this.duration = 10 * 1000; // milliseconds - this.waypoints = []; - - this.useConstantSpeed = true; - this.resamplingCoef = 50; - - this.debugPath = new THREE.Object3D(); - this.debugDummy = new THREE.Object3D(); - - this.animationParent = new THREE.Object3D(); - - this.lookSpeed = 0.005; - this.lookVertical = true; - this.lookHorizontal = true; - this.verticalAngleMap = { srcRange: [ 0, 6.28 ], dstRange: [ 0, 6.28 ] }; - this.horizontalAngleMap = { srcRange: [ 0, 6.28 ], dstRange: [ 0, 6.28 ] }; - - this.domElement = document; - - if ( parameters ) { - - if ( parameters.duration !== undefined ) this.duration = parameters.duration * 1000; - if ( parameters.waypoints !== undefined ) this.waypoints = parameters.waypoints; - - if ( parameters.useConstantSpeed !== undefined ) this.useConstantSpeed = parameters.useConstantSpeed; - if ( parameters.resamplingCoef !== undefined ) this.resamplingCoef = parameters.resamplingCoef; - - if ( parameters.createDebugPath !== undefined ) this.createDebugPath = parameters.createDebugPath; - if ( parameters.createDebugDummy !== undefined ) this.createDebugDummy = parameters.createDebugDummy; - - if ( parameters.lookSpeed !== undefined ) this.lookSpeed = parameters.lookSpeed; - if ( parameters.lookVertical !== undefined ) this.lookVertical = parameters.lookVertical; - if ( parameters.lookHorizontal !== undefined ) this.lookHorizontal = parameters.lookHorizontal; - if ( parameters.verticalAngleMap !== undefined ) this.verticalAngleMap = parameters.verticalAngleMap; - if ( parameters.horizontalAngleMap !== undefined ) this.horizontalAngleMap = parameters.horizontalAngleMap; - - if ( parameters.domElement !== undefined ) this.domElement = parameters.domElement; - - } - - this.mouseX = 0; - this.mouseY = 0; - - this.lat = 0; - this.lon = 0; - - this.phi = 0; - this.theta = 0; - - this.windowHalfX = window.innerWidth / 2; - this.windowHalfY = window.innerHeight / 2; - - var PI2 = Math.PI * 2, - PI180 = Math.PI / 180; - - // methods - - this.update = function ( parentMatrixWorld, forceUpdate, camera ) { - - var srcRange, dstRange; - - if( this.lookHorizontal ) this.lon += this.mouseX * this.lookSpeed; - if( this.lookVertical ) this.lat -= this.mouseY * this.lookSpeed; - - this.lon = Math.max( 0, Math.min( 360, this.lon ) ); - this.lat = Math.max( - 85, Math.min( 85, this.lat ) ); - - this.phi = ( 90 - this.lat ) * PI180; - this.theta = this.lon * PI180; - - this.phi = normalize_angle_rad( this.phi ); - - // constrain vertical look angle - - srcRange = this.verticalAngleMap.srcRange; - dstRange = this.verticalAngleMap.dstRange; - - //this.phi = map_linear( this.phi, srcRange[ 0 ], srcRange[ 1 ], dstRange[ 0 ], dstRange[ 1 ] ); - - var tmpPhi = map_linear( this.phi, srcRange[ 0 ], srcRange[ 1 ], dstRange[ 0 ], dstRange[ 1 ] ); - var tmpPhiFullRange = dstRange[ 1 ] - dstRange[ 0 ]; - var tmpPhiNormalized = ( tmpPhi - dstRange[ 0 ] ) / tmpPhiFullRange; - - this.phi = TWEEN.Easing.Quadratic.EaseInOut( tmpPhiNormalized ) * tmpPhiFullRange + dstRange[ 0 ]; - - // constrain horizontal look angle - - srcRange = this.horizontalAngleMap.srcRange; - dstRange = this.horizontalAngleMap.dstRange; - - //this.theta = map_linear( this.theta, srcRange[ 0 ], srcRange[ 1 ], dstRange[ 0 ], dstRange[ 1 ] ); - - var tmpTheta = map_linear( this.theta, srcRange[ 0 ], srcRange[ 1 ], dstRange[ 0 ], dstRange[ 1 ] ); - var tmpThetaFullRange = dstRange[ 1 ] - dstRange[ 0 ]; - var tmpThetaNormalized = ( tmpTheta - dstRange[ 0 ] ) / tmpThetaFullRange; - - this.theta = TWEEN.Easing.Quadratic.EaseInOut( tmpThetaNormalized ) * tmpThetaFullRange + dstRange[ 0 ]; - - var targetPosition = this.target.position, - position = this.position; - - /* - targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta ); - targetPosition.y = position.y + 100 * Math.cos( this.phi ); - targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta ); - */ - - targetPosition.x = 100 * Math.sin( this.phi ) * Math.cos( this.theta ); - targetPosition.y = 100 * Math.cos( this.phi ); - targetPosition.z = 100 * Math.sin( this.phi ) * Math.sin( this.theta ); - - this.supr.update.call( this, parentMatrixWorld, forceUpdate, camera ); - - }; - - this.onMouseMove = function ( event ) { - - this.mouseX = event.clientX - this.windowHalfX; - this.mouseY = event.clientY - this.windowHalfY; - - }; - - // utils - - function normalize_angle_rad( a ) { - - var b = a % PI2; - return b >= 0 ? b : b + PI2; - - }; - - function cap( x, a, b ) { - - return ( x < a ) ? a : ( ( x > b ) ? b : x ); - - }; - - function map_linear( x, sa, sb, ea, eb ) { - - return ( x - sa ) * ( eb - ea ) / ( sb - sa ) + ea; - - }; - - function distance( a, b ) { - - var dx = a[ 0 ] - b[ 0 ], - dy = a[ 1 ] - b[ 1 ], - dz = a[ 2 ] - b[ 2 ]; - - return Math.sqrt( dx * dx + dy * dy + dz * dz ); - - }; - - function bind( scope, fn ) { - - return function () { - - fn.apply( scope, arguments ); - - }; - - }; - - function initAnimationPath( parent, spline, name, duration ) { - - var animationData = { - - name: name, - fps: 0.6, - length: duration, - - hierarchy: [] - - }; - - var i, - parentAnimation, childAnimation, - path = spline.getControlPointsArray(), - sl = spline.getLength(), - pl = path.length, - t = 0, - first = 0, - last = pl - 1; - - parentAnimation = { parent: -1, keys: [] }; - parentAnimation.keys[ first ] = { time: 0, pos: path[ first ], rot: [ 0, 0, 0, 1 ], scl: [ 1, 1, 1 ] }; - parentAnimation.keys[ last ] = { time: duration, pos: path[ last ], rot: [ 0, 0, 0, 1 ], scl: [ 1, 1, 1 ] }; - - for ( i = 1; i < pl - 1; i++ ) { - - // real distance (approximation via linear segments) - - t = duration * sl.chunks[ i ] / sl.total; - - // equal distance - - //t = duration * ( i / pl ); - - // linear distance - - //t += duration * distance( path[ i ], path[ i - 1 ] ) / sl.total; - - parentAnimation.keys[ i ] = { time: t, pos: path[ i ] }; - - } - - animationData.hierarchy[ 0 ] = parentAnimation; - - THREE.AnimationHandler.add( animationData ); - - return new THREE.Animation( parent, name, THREE.AnimationHandler.CATMULLROM_FORWARD, false ); - - }; - - - function createSplineGeometry( spline, n_sub ) { - - var i, index, position, - geometry = new THREE.Geometry(); - - for ( i = 0; i < spline.points.length * n_sub; i ++ ) { - - index = i / ( spline.points.length * n_sub ); - position = spline.getPoint( index ); - - geometry.vertices[ i ] = new THREE.Vertex( new THREE.Vector3( position.x, position.y, position.z ) ); - - } - - return geometry; - - }; - - function createPath( parent, spline ) { - - var lineGeo = createSplineGeometry( spline, 10 ), - particleGeo = createSplineGeometry( spline, 10 ), - lineMat = new THREE.LineBasicMaterial( { color: 0xff0000, linewidth: 3 } ); - lineObj = new THREE.Line( lineGeo, lineMat ); - particleObj = new THREE.ParticleSystem( particleGeo, new THREE.ParticleBasicMaterial( { color: 0xffaa00, size: 3 } ) ); - - lineObj.scale.set( 1, 1, 1 ); - parent.addChild( lineObj ); - - particleObj.scale.set( 1, 1, 1 ); - parent.addChild( particleObj ); - - var waypoint, - geo = new THREE.SphereGeometry( 1, 16, 8 ), - mat = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); - - for ( i = 0; i < spline.points.length; i++ ) { - - waypoint = new THREE.Mesh( geo, mat ); - waypoint.position.copy( spline.points[ i ] ); - waypoint.updateMatrix(); - parent.addChild( waypoint ); - - } - - }; - - // constructor - - this.spline = new THREE.Spline(); - this.spline.initFromArray( this.waypoints ); - - if ( this.useConstantSpeed ) { - - this.spline.reparametrizeByArcLength( this.resamplingCoef ); - - } - - if ( this.createDebugDummy ) { - - var dummyParentMaterial = new THREE.MeshLambertMaterial( { color: 0x0077ff } ), - dummyChildMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff00 } ), - dummyParentGeo = new THREE.CubeGeometry( 10, 10, 20 ), - dummyChildGeo = new THREE.CubeGeometry( 2, 2, 10 ); - - this.animationParent = new THREE.Mesh( dummyParentGeo, dummyParentMaterial ); - - var dummyChild = new THREE.Mesh( dummyChildGeo, dummyChildMaterial ); - dummyChild.position.set( 0, 10, 0 ); - - this.animation = initAnimationPath( this.animationParent, this.spline, this.id, this.duration ); - - this.animationParent.addChild( this ); - this.animationParent.addChild( this.target ); - this.animationParent.addChild( dummyChild ); - - } else { - - this.animation = initAnimationPath( this.animationParent, this.spline, this.id, this.duration ); - this.animationParent.addChild( this.target ); - this.animationParent.addChild( this ); - - } - - if ( this.createDebugPath ) { - - createPath( this.debugPath, this.spline ); - - } - - this.domElement.addEventListener( 'mousemove', bind( this, this.onMouseMove ), false ); - -}; - -THREE.PathCamera.prototype = new THREE.Camera(); -THREE.PathCamera.prototype.constructor = THREE.PathCamera; -THREE.PathCamera.prototype.supr = THREE.Camera.prototype; - -THREE.PathCameraIdCounter = 0; -/** - * @author James Baicoianu / http://www.baicoianu.com/ - - * parameters = { - * fov: , - * aspect: , - * near: , - * far: , - * target: , - - * movementSpeed: , - * rollSpeed: , - - * noFly: , - * lookVertical: , - * autoForward: , - - * heightSpeed: , - * heightCoef: , - * heightMin: , - * heightMax: , - - * domElement: , - * } - */ - -THREE.FlyCamera = function ( parameters ) { - - THREE.Camera.call( this, parameters.fov, parameters.aspect, parameters.near, parameters.far, parameters.target ); - - this.tmpQuaternion = new THREE.Quaternion(); - - this.movementSpeed = 1.0; - this.rollSpeed = 0.005; - - this.dragToLook = false; - this.autoForward = false; - - this.domElement = document; - - if ( parameters ) { - - if ( parameters.movementSpeed !== undefined ) this.movementSpeed = parameters.movementSpeed; - if ( parameters.rollSpeed !== undefined ) this.rollSpeed = parameters.rollSpeed; - - if ( parameters.dragToLook !== undefined ) this.dragToLook = parameters.dragToLook; - if ( parameters.autoForward !== undefined ) this.autoForward = parameters.autoForward; - - if ( parameters.domElement !== undefined ) this.domElement = parameters.domElement; - - } - - this.useTarget = false; - this.useQuaternion = true; - - this.mouseStatus = 0; - - this.moveState = { up: 0, down: 0, left: 0, right: 0, forward: 0, back: 0, pitchUp: 0, pitchDown: 0, yawLeft: 0, yawRight: 0, rollLeft: 0, rollRight: 0 }; - this.moveVector = new THREE.Vector3( 0, 0, 0 ); - this.rotationVector = new THREE.Vector3( 0, 0, 0 ); - - this.lastUpdate = -1; - this.tdiff = 0; - - this.handleEvent = function ( event ) { - - if ( typeof this[ event.type ] == 'function' ) { - - this[ event.type ]( event ); - - } - - }; - - this.keydown = function( event ) { - - if ( event.altKey ) { - - return; - - } - - switch( event.keyCode ) { - - case 16: /* shift */ this.movementSpeedMultiplier = .1; break; - - case 87: /*W*/ this.moveState.forward = 1; break; - case 83: /*S*/ this.moveState.back = 1; break; - - case 65: /*A*/ this.moveState.left = 1; break; - case 68: /*D*/ this.moveState.right = 1; break; - - case 82: /*R*/ this.moveState.up = 1; break; - case 70: /*F*/ this.moveState.down = 1; break; - - case 38: /*up*/ this.moveState.pitchUp = 1; break; - case 40: /*down*/ this.moveState.pitchDown = 1; break; - - case 37: /*left*/ this.moveState.yawLeft = 1; break; - case 39: /*right*/ this.moveState.yawRight = 1; break; - - case 81: /*Q*/ this.moveState.rollLeft = 1; break; - case 69: /*E*/ this.moveState.rollRight = 1; break; - - } - - this.updateMovementVector(); - this.updateRotationVector(); - - }; - - this.keyup = function( event ) { - - switch( event.keyCode ) { - - case 16: /* shift */ this.movementSpeedMultiplier = 1; break; - - case 87: /*W*/ this.moveState.forward = 0; break; - case 83: /*S*/ this.moveState.back = 0; break; - - case 65: /*A*/ this.moveState.left = 0; break; - case 68: /*D*/ this.moveState.right = 0; break; - - case 82: /*R*/ this.moveState.up = 0; break; - case 70: /*F*/ this.moveState.down = 0; break; - - case 38: /*up*/ this.moveState.pitchUp = 0; break; - case 40: /*down*/ this.moveState.pitchDown = 0; break; - - case 37: /*left*/ this.moveState.yawLeft = 0; break; - case 39: /*right*/ this.moveState.yawRight = 0; break; - - case 81: /*Q*/ this.moveState.rollLeft = 0; break; - case 69: /*E*/ this.moveState.rollRight = 0; break; - - } - - this.updateMovementVector(); - this.updateRotationVector(); - - }; - - this.mousedown = function(event) { - - event.preventDefault(); - event.stopPropagation(); - - if ( this.dragToLook ) { - - this.mouseStatus ++; - - } else { - - switch ( event.button ) { - - case 0: this.moveForward = true; break; - case 2: this.moveBackward = true; break; - - } - - } - - }; - - this.mousemove = function( event ) { - - if ( !this.dragToLook || this.mouseStatus > 0 ) { - - var container = this.getContainerDimensions(); - var halfWidth = container.size[ 0 ] / 2; - var halfHeight = container.size[ 1 ] / 2; - - this.moveState.yawLeft = - ( ( event.clientX - container.offset[ 0 ] ) - halfWidth ) / halfWidth; - this.moveState.pitchDown = ( ( event.clientY - container.offset[ 1 ] ) - halfHeight ) / halfHeight; - this.updateRotationVector(); - - } - - }; - - this.mouseup = function( event ) { - - event.preventDefault(); - event.stopPropagation(); - - if ( this.dragToLook ) { - - this.mouseStatus --; - - //this.mouseX = this.mouseY = 0; - this.moveState.yawLeft = this.moveState.pitchDown = 0; - - } else { - - switch ( event.button ) { - - case 0: this.moveForward = false; break; - case 2: this.moveBackward = false; break; - - } - - } - - this.updateRotationVector(); - - }; - - this.update = function( parentMatrixWorld, forceUpdate, camera ) { - - var now = new Date().getTime(); - - if ( this.lastUpdate == -1 ) this.lastUpdate = now; - - this.tdiff = ( now - this.lastUpdate ) / 1000; - this.lastUpdate = now; - - //this.position.addSelf( this.moveVector.multiplyScalar( tdiff ) ); - var moveMult = this.tdiff * this.movementSpeed; - var rotMult = this.tdiff * this.rollSpeed; - - this.translateX( this.moveVector.x * moveMult ); - this.translateY( this.moveVector.y * moveMult ); - this.translateZ( this.moveVector.z * moveMult ); - - this.tmpQuaternion.set( this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1 ).normalize(); - this.quaternion.multiplySelf( this.tmpQuaternion ); - - this.matrix.setPosition( this.position ); - this.matrix.setRotationFromQuaternion( this.quaternion ); - this.matrixWorldNeedsUpdate = true; - - this.supr.update.call( this ); - - }; - - this.updateMovementVector = function() { - - var forward = ( this.moveState.forward || ( this.autoForward && !this.moveState.back ) ) ? 1 : 0; - - this.moveVector.x = ( -this.moveState.left + this.moveState.right ); - this.moveVector.y = ( -this.moveState.down + this.moveState.up ); - this.moveVector.z = ( -forward + this.moveState.back ); - - //console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] ); - - }; - - this.updateRotationVector = function() { - - this.rotationVector.x = ( -this.moveState.pitchDown + this.moveState.pitchUp ); - this.rotationVector.y = ( -this.moveState.yawRight + this.moveState.yawLeft ); - this.rotationVector.z = ( -this.moveState.rollRight + this.moveState.rollLeft ); - - //console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] ); - - }; - - this.getContainerDimensions = function() { - - if ( this.domElement != document ) { - - return { - size : [ this.domElement.offsetWidth, this.domElement.offsetHeight ], - offset : [ this.domElement.offsetLeft, this.domElement.offsetTop ] - }; - - } else { - - return { - size : [ window.innerWidth, window.innerHeight ], - offset : [ 0, 0 ] - }; - - } - - }; - - function bind( scope, fn ) { - - return function () { - - fn.apply( scope, arguments ); - - }; - - }; - - this.domElement.addEventListener( 'mousemove', bind( this, this.mousemove ), false ); - this.domElement.addEventListener( 'mousedown', bind( this, this.mousedown ), false ); - this.domElement.addEventListener( 'mouseup', bind( this, this.mouseup ), false ); - - window.addEventListener( 'keydown', bind( this, this.keydown ), false ); - window.addEventListener( 'keyup', bind( this, this.keyup ), false ); - - this.updateMovementVector(); - this.updateRotationVector(); - -}; - -THREE.FlyCamera.prototype = new THREE.Camera(); -THREE.FlyCamera.prototype.constructor = THREE.FlyCamera; -THREE.FlyCamera.prototype.supr = THREE.Camera.prototype; -/** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * fov: , - * aspect: , - * near: , - * far: , - - * movementSpeed: , - * lookSpeed: , - * rollSpeed: , - - * autoForward: , - * mouseLook: , - - * domElement: , - * } - */ - -THREE.RollCamera = function ( fov, aspect, near, far ) { - - THREE.Camera.call( this, fov, aspect, near, far ); - - // API - - this.mouseLook = true; - this.autoForward = false; - - this.lookSpeed = 1; - this.movementSpeed = 1; - this.rollSpeed = 1; - - this.constrainVertical = [ -0.9, 0.9 ]; - - this.domElement = document; - - // disable default camera behavior - - this.useTarget = false; - this.matrixAutoUpdate = false; - - // internals - - this.forward = new THREE.Vector3( 0, 0, 1 ); - this.roll = 0; - - this.lastUpdate = -1; - this.delta = 0; - - var xTemp = new THREE.Vector3(); - var yTemp = new THREE.Vector3(); - var zTemp = new THREE.Vector3(); - var rollMatrix = new THREE.Matrix4(); - - var doRoll = false, rollDirection = 1, forwardSpeed = 0, sideSpeed = 0, upSpeed = 0; - - var mouseX = 0, mouseY = 0; - - var windowHalfX = window.innerWidth / 2; - var windowHalfY = window.innerHeight / 2; - - // custom update - - this.update = function() { - - var now = new Date().getTime(); - - if ( this.lastUpdate == -1 ) this.lastUpdate = now; - - this.delta = ( now - this.lastUpdate ) / 1000; - this.lastUpdate = now; - - if ( this.mouseLook ) { - - var actualLookSpeed = this.delta * this.lookSpeed; - - this.rotateHorizontally( actualLookSpeed * mouseX ); - this.rotateVertically( actualLookSpeed * mouseY ); - - } - - var actualSpeed = this.delta * this.movementSpeed; - var forwardOrAuto = ( forwardSpeed > 0 || ( this.autoForward && ! ( forwardSpeed < 0 ) ) ) ? 1 : forwardSpeed; - - this.translateZ( actualSpeed * forwardOrAuto ); - this.translateX( actualSpeed * sideSpeed ); - this.translateY( actualSpeed * upSpeed ); - - if( doRoll ) { - - this.roll += this.rollSpeed * this.delta * rollDirection; - - } - - // cap forward up / down - - if( this.forward.y > this.constrainVertical[ 1 ] ) { - - this.forward.y = this.constrainVertical[ 1 ]; - this.forward.normalize(); - - } else if( this.forward.y < this.constrainVertical[ 0 ] ) { - - this.forward.y = this.constrainVertical[ 0 ]; - this.forward.normalize(); - - } - - - // construct unrolled camera matrix - - zTemp.copy( this.forward ); - yTemp.set( 0, 1, 0 ); - - xTemp.cross( yTemp, zTemp ).normalize(); - yTemp.cross( zTemp, xTemp ).normalize(); - - this.matrix.n11 = xTemp.x; this.matrix.n12 = yTemp.x; this.matrix.n13 = zTemp.x; - this.matrix.n21 = xTemp.y; this.matrix.n22 = yTemp.y; this.matrix.n23 = zTemp.y; - this.matrix.n31 = xTemp.z; this.matrix.n32 = yTemp.z; this.matrix.n33 = zTemp.z; - - - // calculate roll matrix - - rollMatrix.identity(); - rollMatrix.n11 = Math.cos( this.roll ); rollMatrix.n12 = -Math.sin( this.roll ); - rollMatrix.n21 = Math.sin( this.roll ); rollMatrix.n22 = Math.cos( this.roll ); - - - // multiply camera with roll - - this.matrix.multiplySelf( rollMatrix ); - this.matrixWorldNeedsUpdate = true; - - - // set position - - this.matrix.n14 = this.position.x; - this.matrix.n24 = this.position.y; - this.matrix.n34 = this.position.z; - - - // call supr - - this.supr.update.call( this ); - - }; - - this.translateX = function ( distance ) { - - this.position.x += this.matrix.n11 * distance; - this.position.y += this.matrix.n21 * distance; - this.position.z += this.matrix.n31 * distance; - - }; - - this.translateY = function ( distance ) { - - this.position.x += this.matrix.n12 * distance; - this.position.y += this.matrix.n22 * distance; - this.position.z += this.matrix.n32 * distance; - - }; - - this.translateZ = function ( distance ) { - - this.position.x -= this.matrix.n13 * distance; - this.position.y -= this.matrix.n23 * distance; - this.position.z -= this.matrix.n33 * distance; - - }; - - - this.rotateHorizontally = function ( amount ) { - - // please note that the amount is NOT degrees, but a scale value - - xTemp.set( this.matrix.n11, this.matrix.n21, this.matrix.n31 ); - xTemp.multiplyScalar( amount ); - - this.forward.subSelf( xTemp ); - this.forward.normalize(); - - }; - - this.rotateVertically = function ( amount ) { - - // please note that the amount is NOT degrees, but a scale value - - yTemp.set( this.matrix.n12, this.matrix.n22, this.matrix.n32 ); - yTemp.multiplyScalar( amount ); - - this.forward.addSelf( yTemp ); - this.forward.normalize(); - - }; - - function onKeyDown( event ) { - - switch( event.keyCode ) { - - case 38: /*up*/ - case 87: /*W*/ forwardSpeed = 1; break; - - case 37: /*left*/ - case 65: /*A*/ sideSpeed = -1; break; - - case 40: /*down*/ - case 83: /*S*/ forwardSpeed = -1; break; - - case 39: /*right*/ - case 68: /*D*/ sideSpeed = 1; break; - - case 81: /*Q*/ doRoll = true; rollDirection = 1; break; - case 69: /*E*/ doRoll = true; rollDirection = -1; break; - - case 82: /*R*/ upSpeed = 1; break; - case 70: /*F*/ upSpeed = -1; break; - - } - - }; - - function onKeyUp( event ) { - - switch( event.keyCode ) { - - case 38: /*up*/ - case 87: /*W*/ forwardSpeed = 0; break; - - case 37: /*left*/ - case 65: /*A*/ sideSpeed = 0; break; - - case 40: /*down*/ - case 83: /*S*/ forwardSpeed = 0; break; - - case 39: /*right*/ - case 68: /*D*/ sideSpeed = 0; break; - - case 81: /*Q*/ doRoll = false; break; - case 69: /*E*/ doRoll = false; break; - - case 82: /*R*/ upSpeed = 0; break; - case 70: /*F*/ upSpeed = 0; break; - - } - - }; - - function onMouseMove( event ) { - - mouseX = ( event.clientX - windowHalfX ) / window.innerWidth; - mouseY = ( event.clientY - windowHalfY ) / window.innerHeight; - - }; - - function onMouseDown ( event ) { - - event.preventDefault(); - event.stopPropagation(); - - switch ( event.button ) { - - case 0: forwardSpeed = 1; break; - case 2: forwardSpeed = -1; break; - - } - - }; - - function onMouseUp ( event ) { - - event.preventDefault(); - event.stopPropagation(); - - switch ( event.button ) { - - case 0: forwardSpeed = 0; break; - case 2: forwardSpeed = 0; break; - - } - - }; - - this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); - - this.domElement.addEventListener( 'mousemove', onMouseMove, false ); - this.domElement.addEventListener( 'mousedown', onMouseDown, false ); - this.domElement.addEventListener( 'mouseup', onMouseUp, false ); - this.domElement.addEventListener( 'keydown', onKeyDown, false ); - this.domElement.addEventListener( 'keyup', onKeyUp, false ); - -}; - - -THREE.RollCamera.prototype = new THREE.Camera(); -THREE.RollCamera.prototype.constructor = THREE.RollCamera; -THREE.RollCamera.prototype.supr = THREE.Camera.prototype; - - -/** - * @author Eberhard Graether / http://egraether.com/ - - * parameters = { - * fov: , - * aspect: , - * near: , - * far: , - * target: , - - * radius: , - * screen: { width : , height : , offsetLeft : , offsetTop : }, - - * rotateSpeed: , - * zoomSpeed: , - * panSpeed: , - - * noZoom: , - * noPan: , - - * staticMoving: , - * dynamicDampingFactor: , - - * minDistance: , - * maxDistance: , - - * keys: , // [ rotateKey, zoomKey, panKey ], - - * domElement: , - * } - */ - -THREE.TrackballCamera = function ( parameters ) { - - // target.position is modified when panning - - parameters = parameters || {}; - - THREE.Camera.call( this, parameters.fov, parameters.aspect, parameters.near, parameters.far, parameters.target ); - - this.domElement = parameters.domElement || document; - - this.screen = parameters.screen || { width : window.innerWidth, height : window.innerHeight, offsetLeft : 0, offsetTop : 0 }; - this.radius = parameters.radius || ( this.screen.width + this.screen.height ) / 4; - - this.rotateSpeed = parameters.rotateSpeed || 1.0; - this.zoomSpeed = parameters.zoomSpeed || 1.2; - this.panSpeed = parameters.panSpeed || 0.3; - - this.noZoom = parameters.noZoom || false; - this.noPan = parameters.noPan || false; - - this.staticMoving = parameters.staticMoving || false; - this.dynamicDampingFactor = parameters.dynamicDampingFactor || 0.2; - - this.minDistance = parameters.minDistance || 0; - this.maxDistance = parameters.maxDistance || Infinity; - - this.keys = parameters.keys || [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ]; - - this.useTarget = true; - - - //internals - - var _keyPressed = false, - _state = this.STATE.NONE, - - _eye = new THREE.Vector3(), - - _rotateStart = new THREE.Vector3(), - _rotateEnd = new THREE.Vector3(), - - _zoomStart = new THREE.Vector2(), - _zoomEnd = new THREE.Vector2(), - - _panStart = new THREE.Vector2(), - _panEnd = new THREE.Vector2(); - - - // methods - - this.handleEvent = function ( event ) { - - if ( typeof this[ event.type ] == 'function' ) { - - this[ event.type ]( event ); - - } - - }; - - this.getMouseOnScreen = function( clientX, clientY ) { - - return new THREE.Vector2( - ( clientX - this.screen.offsetLeft ) / this.radius * 0.5, - ( clientY - this.screen.offsetTop ) / this.radius * 0.5 - ); - - }; - - this.getMouseProjectionOnBall = function( clientX, clientY ) { - - var mouseOnBall = new THREE.Vector3( - ( clientX - this.screen.width * 0.5 - this.screen.offsetLeft ) / this.radius, - ( this.screen.height * 0.5 + this.screen.offsetTop - clientY ) / this.radius, - 0.0 - ); - - var length = mouseOnBall.length(); - - if ( length > 1.0 ) { - - mouseOnBall.normalize(); - - } else { - - mouseOnBall.z = Math.sqrt( 1.0 - length * length ); - - } - - _eye = this.position.clone().subSelf( this.target.position ); - - var projection = this.up.clone().setLength( mouseOnBall.y ); - projection.addSelf( this.up.clone().crossSelf( _eye ).setLength( mouseOnBall.x ) ); - projection.addSelf( _eye.setLength( mouseOnBall.z ) ); - - return projection; - - }; - - this.rotateCamera = function() { - - var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() ); - - if ( angle ) { - - var axis = (new THREE.Vector3()).cross( _rotateStart, _rotateEnd ).normalize(), - quaternion = new THREE.Quaternion(); - - angle *= this.rotateSpeed; - - quaternion.setFromAxisAngle( axis, -angle ); - - quaternion.multiplyVector3( _eye ); - quaternion.multiplyVector3( this.up ); - - quaternion.multiplyVector3( _rotateEnd ); - - if ( this.staticMoving ) { - - _rotateStart = _rotateEnd; - - } else { - - quaternion.setFromAxisAngle( axis, angle * ( this.dynamicDampingFactor - 1.0 ) ); - quaternion.multiplyVector3( _rotateStart ); - - } - - } - - }; - - this.zoomCamera = function() { - - var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * this.zoomSpeed; - - if ( factor !== 1.0 && factor > 0.0 ) { - - _eye.multiplyScalar( factor ); - - if ( this.staticMoving ) { - - _zoomStart = _zoomEnd; - - } else { - - _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor; - - } - - } - - }; - - this.panCamera = function() { - - var mouseChange = _panEnd.clone().subSelf( _panStart ); - - if ( mouseChange.lengthSq() ) { - - mouseChange.multiplyScalar( _eye.length() * this.panSpeed ); - - var pan = _eye.clone().crossSelf( this.up ).setLength( mouseChange.x ); - pan.addSelf( this.up.clone().setLength( mouseChange.y ) ); - - this.position.addSelf( pan ); - this.target.position.addSelf( pan ); - - if ( this.staticMoving ) { - - _panStart = _panEnd; - - } else { - - _panStart.addSelf( mouseChange.sub( _panEnd, _panStart ).multiplyScalar( this.dynamicDampingFactor ) ); - - } - - } - - }; - - this.checkDistances = function() { - - if ( !this.noZoom || !this.noPan ) { - - if ( this.position.lengthSq() > this.maxDistance * this.maxDistance ) { - - this.position.setLength( this.maxDistance ); - - } - - if ( _eye.lengthSq() < this.minDistance * this.minDistance ) { - - this.position.add( this.target.position, _eye.setLength( this.minDistance ) ); - - } - - } - - }; - - this.update = function( parentMatrixWorld, forceUpdate, camera ) { - - _eye = this.position.clone().subSelf( this.target.position ), - - this.rotateCamera(); - - if ( !this.noZoom ) { - - this.zoomCamera(); - - } - - if ( !this.noPan ) { - - this.panCamera(); - - } - - this.position.add( this.target.position, _eye ); - - this.checkDistances(); - - this.supr.update.call( this, parentMatrixWorld, forceUpdate, camera ); - - }; - - - // listeners - - function keydown( event ) { - - if ( _state !== this.STATE.NONE ) { - - return; - - } else if ( event.keyCode === this.keys[ this.STATE.ROTATE ] ) { - - _state = this.STATE.ROTATE; - - } else if ( event.keyCode === this.keys[ this.STATE.ZOOM ] && !this.noZoom ) { - - _state = this.STATE.ZOOM; - - } else if ( event.keyCode === this.keys[ this.STATE.PAN ] && !this.noPan ) { - - _state = this.STATE.PAN; - - } - - if ( _state !== this.STATE.NONE ) { - - _keyPressed = true; - - } - - }; - - function keyup( event ) { - - if ( _state !== this.STATE.NONE ) { - - _state = this.STATE.NONE; - - } - - }; - - function mousedown(event) { - - event.preventDefault(); - event.stopPropagation(); - - if ( _state === this.STATE.NONE ) { - - _state = event.button; - - if ( _state === this.STATE.ROTATE ) { - - _rotateStart = _rotateEnd = this.getMouseProjectionOnBall( event.clientX, event.clientY ); - - } else if ( _state === this.STATE.ZOOM && !this.noZoom ) { - - _zoomStart = _zoomEnd = this.getMouseOnScreen( event.clientX, event.clientY ); - - } else if ( !this.noPan ) { - - _panStart = _panEnd = this.getMouseOnScreen( event.clientX, event.clientY ); - - } - - } - - }; - - function mousemove( event ) { - - if ( _keyPressed ) { - - _rotateStart = _rotateEnd = this.getMouseProjectionOnBall( event.clientX, event.clientY ); - _zoomStart = _zoomEnd = this.getMouseOnScreen( event.clientX, event.clientY ); - _panStart = _panEnd = this.getMouseOnScreen( event.clientX, event.clientY ); - - _keyPressed = false; - - } - - if ( _state === this.STATE.NONE ) { - - return; - - } else if ( _state === this.STATE.ROTATE ) { - - _rotateEnd = this.getMouseProjectionOnBall( event.clientX, event.clientY ); - - } else if ( _state === this.STATE.ZOOM && !this.noZoom ) { - - _zoomEnd = this.getMouseOnScreen( event.clientX, event.clientY ); - - } else if ( _state === this.STATE.PAN && !this.noPan ) { - - _panEnd = this.getMouseOnScreen( event.clientX, event.clientY ); - - } - - }; - - function mouseup( event ) { - - event.preventDefault(); - event.stopPropagation(); - - _state = this.STATE.NONE; - - }; - - function bind( scope, fn ) { - - return function () { - - fn.apply( scope, arguments ); - - }; - - }; - - this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); - - this.domElement.addEventListener( 'mousemove', bind( this, mousemove ), false ); - this.domElement.addEventListener( 'mousedown', bind( this, mousedown ), false ); - this.domElement.addEventListener( 'mouseup', bind( this, mouseup ), false ); - - window.addEventListener( 'keydown', bind( this, keydown ), false ); - window.addEventListener( 'keyup', bind( this, keyup ), false ); - -}; - -THREE.TrackballCamera.prototype = new THREE.Camera(); -THREE.TrackballCamera.prototype.constructor = THREE.TrackballCamera; -THREE.TrackballCamera.prototype.supr = THREE.Camera.prototype; - -THREE.TrackballCamera.prototype.STATE = { NONE : -1, ROTATE : 0, ZOOM : 1, PAN : 2 }; -/** - * @author chriskillpack / http://chriskillpack.com/ - * - * QuakeCamera has been renamed FPCamera. This property exists for backwards - * compatibility only. - */ -THREE.QuakeCamera = THREE.FPCamera; -/** - * @author mr.doob / http://mrdoob.com/ - * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Cube.as - */ - -THREE.CubeGeometry = function ( width, height, depth, segmentsWidth, segmentsHeight, segmentsDepth, materials, flipped, sides ) { - - THREE.Geometry.call( this ); - - var scope = this, - width_half = width / 2, - height_half = height / 2, - depth_half = depth / 2, - flip = flipped ? - 1 : 1; - - if ( materials !== undefined ) { - - if ( materials instanceof Array ) { - - this.materials = materials; - - } else { - - this.materials = []; - - for ( var i = 0; i < 6; i ++ ) { - - this.materials.push( [ materials ] ); - - } - - } - - } else { - - this.materials = []; - - } - - this.sides = { px: true, nx: true, py: true, ny: true, pz: true, nz: true }; - - if( sides != undefined ) { - - for( var s in sides ) { - - if ( this.sides[ s ] != undefined ) { - - this.sides[ s ] = sides[ s ]; - - } - - } - - } - - this.sides.px && buildPlane( 'z', 'y', 1 * flip, - 1, depth, height, - width_half, this.materials[ 0 ] ); // px - this.sides.nx && buildPlane( 'z', 'y', - 1 * flip, - 1, depth, height, width_half, this.materials[ 1 ] ); // nx - this.sides.py && buildPlane( 'x', 'z', 1 * flip, 1, width, depth, height_half, this.materials[ 2 ] ); // py - this.sides.ny && buildPlane( 'x', 'z', 1 * flip, - 1, width, depth, - height_half, this.materials[ 3 ] ); // ny - this.sides.pz && buildPlane( 'x', 'y', 1 * flip, - 1, width, height, depth_half, this.materials[ 4 ] ); // pz - this.sides.nz && buildPlane( 'x', 'y', - 1 * flip, - 1, width, height, - depth_half, this.materials[ 5 ] ); // nz - - mergeVertices(); - - function buildPlane( u, v, udir, vdir, width, height, depth, material ) { - - var w, ix, iy, - gridX = segmentsWidth || 1, - gridY = segmentsHeight || 1, - width_half = width / 2, - height_half = height / 2, - offset = scope.vertices.length; - - if ( ( u == 'x' && v == 'y' ) || ( u == 'y' && v == 'x' ) ) { - - w = 'z'; - - } else if ( ( u == 'x' && v == 'z' ) || ( u == 'z' && v == 'x' ) ) { - - w = 'y'; - gridY = segmentsDepth || 1; - - } else if ( ( u == 'z' && v == 'y' ) || ( u == 'y' && v == 'z' ) ) { - - w = 'x'; - gridX = segmentsDepth || 1; - - } - - var gridX1 = gridX + 1, - gridY1 = gridY + 1, - segment_width = width / gridX, - segment_height = height / gridY; - - for( iy = 0; iy < gridY1; iy++ ) { - - for( ix = 0; ix < gridX1; ix++ ) { - - var vector = new THREE.Vector3(); - vector[ u ] = ( ix * segment_width - width_half ) * udir; - vector[ v ] = ( iy * segment_height - height_half ) * vdir; - vector[ w ] = depth; - - scope.vertices.push( new THREE.Vertex( vector ) ); - - } - - } - - for( iy = 0; iy < gridY; iy++ ) { - - for( ix = 0; ix < gridX; ix++ ) { - - var a = ix + gridX1 * iy; - var b = ix + gridX1 * ( iy + 1 ); - var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); - var d = ( ix + 1 ) + gridX1 * iy; - - scope.faces.push( new THREE.Face4( a + offset, b + offset, c + offset, d + offset, null, null, material ) ); - scope.faceVertexUvs[ 0 ].push( [ - new THREE.UV( ix / gridX, iy / gridY ), - new THREE.UV( ix / gridX, ( iy + 1 ) / gridY ), - new THREE.UV( ( ix + 1 ) / gridX, ( iy + 1 ) / gridY ), - new THREE.UV( ( ix + 1 ) / gridX, iy / gridY ) - ] ); - - } - - } - - } - - function mergeVertices() { - - var unique = [], changes = []; - - for ( var i = 0, il = scope.vertices.length; i < il; i ++ ) { - - var v = scope.vertices[ i ], - duplicate = false; - - for ( var j = 0, jl = unique.length; j < jl; j ++ ) { - - var vu = unique[ j ]; - - if( v.position.x == vu.position.x && v.position.y == vu.position.y && v.position.z == vu.position.z ) { - - changes[ i ] = j; - duplicate = true; - break; - - } - - } - - if ( ! duplicate ) { - - changes[ i ] = unique.length; - unique.push( new THREE.Vertex( v.position.clone() ) ); - - } - - } - - for ( i = 0, il = scope.faces.length; i < il; i ++ ) { - - var face = scope.faces[ i ]; - - face.a = changes[ face.a ]; - face.b = changes[ face.b ]; - face.c = changes[ face.c ]; - face.d = changes[ face.d ]; - - } - - scope.vertices = unique; - - } - - this.computeCentroids(); - this.computeFaceNormals(); - -}; - -THREE.CubeGeometry.prototype = new THREE.Geometry(); -THREE.CubeGeometry.prototype.constructor = THREE.CubeGeometry; -/** - * @author kile / http://kile.stravaganza.org/ - * @author mr.doob / http://mrdoob.com/ - * @author fuzzthink - */ - -THREE.CylinderGeometry = function ( numSegs, topRad, botRad, height, topOffset, botOffset ) { - - THREE.Geometry.call( this ); - - var scope = this, i, PI2 = Math.PI * 2, halfHeight = height / 2; - - // Top circle vertices - - for ( i = 0; i < numSegs; i ++ ) { - - v( Math.sin( PI2 * i / numSegs ) * topRad, Math.cos( PI2 * i / numSegs ) * topRad, - halfHeight ); - - } - - // Bottom circle vertices - - for ( i = 0; i < numSegs; i ++ ) { - - v( Math.sin( PI2 * i / numSegs ) * botRad, Math.cos( PI2 * i / numSegs ) * botRad, halfHeight ); - - } - - // Body faces - - for ( i = 0; i < numSegs; i++ ) { - - f4( - i, - i + numSegs, - numSegs + ( i + 1 ) % numSegs, - ( i + 1 ) % numSegs - ); - - } - - // Bottom circle faces - - if ( botRad > 0 ) { - - v( 0, 0, - halfHeight - ( botOffset || 0 ) ); - - for ( i = numSegs; i < numSegs + ( numSegs / 2 ); i++ ) { - - f4( - 2 * numSegs, - ( 2 * i - 2 * numSegs ) % numSegs, - ( 2 * i - 2 * numSegs + 1 ) % numSegs, - ( 2 * i - 2 * numSegs + 2 ) % numSegs - ); - - } - - } - - // Top circle faces - - if ( topRad > 0 ) { - - v( 0, 0, halfHeight + ( topOffset || 0 ) ); - - for ( i = numSegs + ( numSegs / 2 ); i < 2 * numSegs; i ++ ) { - - f4( - 2 * numSegs + 1, - ( 2 * i - 2 * numSegs + 2 ) % numSegs + numSegs, - ( 2 * i - 2 * numSegs + 1 ) % numSegs + numSegs, - ( 2 * i - 2 * numSegs ) % numSegs + numSegs - ); - - } - - } - - // Cylindrical mapping - - for ( var i = 0, il = this.faces.length; i < il; i ++ ) { - - var uvs = [], face = this.faces[ i ], - a = this.vertices[ face.a ], - b = this.vertices[ face.b ], - c = this.vertices[ face.c ], - d = this.vertices[ face.d ]; - - uvs.push( new THREE.UV( 0.5 + Math.atan2( a.position.x, a.position.y ) / PI2, 0.5 + ( a.position.z / height ) ) ); - uvs.push( new THREE.UV( 0.5 + Math.atan2( b.position.x, b.position.y ) / PI2, 0.5 + ( b.position.z / height ) ) ); - uvs.push( new THREE.UV( 0.5 + Math.atan2( c.position.x, c.position.y ) / PI2, 0.5 + ( c.position.z / height ) ) ); - - if ( face instanceof THREE.Face4 ) { - - uvs.push( new THREE.UV( 0.5 + ( Math.atan2( d.position.x, d.position.y ) / PI2 ), 0.5 + ( d.position.z / height ) ) ); - - } - - this.faceVertexUvs[ 0 ].push( uvs ); - - } - - this.computeCentroids(); - this.computeFaceNormals(); - // this.computeVertexNormals(); - - function v( x, y, z ) { - - scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) ); - - } - - function f4( a, b, c, d ) { - - scope.faces.push( new THREE.Face4( a, b, c, d ) ); - - } - -}; - -THREE.CylinderGeometry.prototype = new THREE.Geometry(); -THREE.CylinderGeometry.prototype.constructor = THREE.CylinderGeometry; -/** - * @author oosmoxiecode - - * uvs are messed up in this one, and commented away for now. There is an ugly "seam" by the shared vertices - * when it "wraps" around, that needs to be fixed. It´s because they share the first and the last vertices - * so it draws the entire texture on the seam-faces, I think... - */ - -THREE.IcosahedronGeometry = function ( subdivisions ) { - - var scope = this; - var tempScope = new THREE.Geometry(); - var tempFaces; - this.subdivisions = subdivisions || 0; - - //var temp_uv = []; - - THREE.Geometry.call(this); - - // create 12 vertices of a Icosahedron - var t = (1 + Math.sqrt(5)) / 2; - - v(-1, t, 0); - v( 1, t, 0); - v(-1, -t, 0); - v( 1, -t, 0); - - v( 0, -1, t); - v( 0, 1, t); - v( 0, -1, -t); - v( 0, 1, -t); - - v( t, 0, -1); - v( t, 0, 1); - v(-t, 0, -1); - v(-t, 0, 1); - - // 5 faces around point 0 - f3(0, 11, 5, tempScope); - f3(0, 5, 1, tempScope); - f3(0, 1, 7, tempScope); - f3(0, 7, 10, tempScope); - f3(0, 10, 11, tempScope); - - // 5 adjacent faces - f3(1, 5, 9, tempScope); - f3(5, 11, 4, tempScope); - f3(11, 10, 2, tempScope); - f3(10, 7, 6, tempScope); - f3(7, 1, 8, tempScope); - - // 5 faces around point 3 - f3(3, 9, 4, tempScope); - f3(3, 4, 2, tempScope); - f3(3, 2, 6, tempScope); - f3(3, 6, 8, tempScope); - f3(3, 8, 9, tempScope); - - // 5 adjacent faces - f3(4, 9, 5, tempScope); - f3(2, 4, 11, tempScope); - f3(6, 2, 10, tempScope); - f3(8, 6, 7, tempScope); - f3(9, 8, 1, tempScope); - - // subdivide faces to refine the triangles - for (var i=0; i < this.subdivisions; i++) { - tempFaces = new THREE.Geometry(); - for (var tri in tempScope.faces) { - // replace each triangle by 4 triangles - var a = getMiddlePoint(tempScope.faces[tri].a, tempScope.faces[tri].b); - var b = getMiddlePoint(tempScope.faces[tri].b, tempScope.faces[tri].c); - var c = getMiddlePoint(tempScope.faces[tri].c, tempScope.faces[tri].a); - - f3(tempScope.faces[tri].a, a, c, tempFaces); - f3(tempScope.faces[tri].b, b, a, tempFaces); - f3(tempScope.faces[tri].c, c, b, tempFaces); - f3(a, b, c, tempFaces); - } - tempScope.faces = tempFaces.faces; - //tempScope.uvs = tempFaces.uvs; - } - - scope.faces = tempScope.faces; - //scope.uvs = tempScope.uvs; - - delete tempScope; - delete tempFaces; - - this.computeCentroids(); - this.computeFaceNormals(); - this.computeVertexNormals(); - - function v( x, y, z ) { - var length = Math.sqrt(x * x + y * y + z * z); - var i = scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x/length, y/length, z/length ) ) ); - - //var uv = getUv(x, y, z); - //temp_uv.push(uv); - - return i-1; - } - - function f3( a, b, c, inscope ) { - inscope.faces.push( new THREE.Face3( a, b, c ) ); - - /*inscope.uvs.push( [new THREE.UV( temp_uv[a].u, temp_uv[a].v ), - new THREE.UV( temp_uv[b].u, temp_uv[b].v ), - new THREE.UV( temp_uv[c].u, temp_uv[c].v ) - ] ); - */ - } - - function getMiddlePoint(p1,p2) { - var pos1 = scope.vertices[p1].position; - var pos2 = scope.vertices[p2].position; - - var x = (pos1.x + pos2.x) / 2; - var y = (pos1.y + pos2.y) / 2; - var z = (pos1.z + pos2.z) / 2; - - var i = v(x, y, z); - return i; - } - - /*function getUv(x,y,z) { - - var u,v; - var px,py,pz,d; - - d = Math.sqrt( x*x+y*y+z*z ); - - px = x/d; - py = y/d; - pz = z/d; - - var normalisedX = 0; - var normalisedZ = -1; - - if (((px * px) + (pz * pz)) > 0) { - normalisedX = Math.sqrt((px * px) / ((px * px) + (pz * pz))); - - if (px < 0) { - normalisedX = -normalisedX; - } - - normalisedZ = Math.sqrt((pz * pz) / ((px * px) + (pz * pz))); - - if (pz < 0) { - normalisedZ = -normalisedZ; - } - } - - if (normalisedZ == 0) { - u = ((normalisedX * Math.PI) / 2); - } else { - u = Math.atan(normalisedX / normalisedZ); - - if (normalisedZ < 0) { - u += Math.PI; - } - } - - if (u < 0) { - u += 2 * Math.PI; - } - - u /= 2 * Math.PI; - v = (-py + 1) / 2; - - return {u:u,v:v}; - }*/ - -} - -THREE.IcosahedronGeometry.prototype = new THREE.Geometry(); -THREE.IcosahedronGeometry.prototype.constructor = THREE.IcosahedronGeometry; -/** - * @author astrodud / http://astrodud.isgreat.org/ - */ - -THREE.LatheGeometry = function ( points, steps, angle ) { - - THREE.Geometry.call( this ); - - this.steps = steps || 12; - this.angle = angle || 2 * Math.PI; - - var stepSize = this.angle / this.steps, - newV = [], oldInds = [], newInds = [], startInds = [], - matrix = new THREE.Matrix4().setRotationZ( stepSize ); - - for ( var j = 0; j < points.length; j ++ ) { - - this.vertices.push( new THREE.Vertex( points[ j ] ) ); - - newV[ j ] = points[ j ].clone(); - oldInds[ j ] = this.vertices.length - 1; - - } - - for ( var r = 0; r <= this.angle + 0.001; r += stepSize ) { // need the +0.001 for it go up to angle - - for ( var j = 0; j < newV.length; j ++ ) { - - if ( r < this.angle ) { - - newV[ j ] = matrix.multiplyVector3( newV[ j ].clone() ); - this.vertices.push( new THREE.Vertex( newV[ j ] ) ); - newInds[ j ] = this.vertices.length - 1; - - } else { - - newInds = startInds; // wrap it up! - - } - - } - - if ( r == 0 ) startInds = oldInds; - - for ( var j = 0; j < oldInds.length - 1; j ++ ) { - - this.faces.push( new THREE.Face4( newInds[ j ], newInds[ j + 1 ], oldInds[ j + 1 ], oldInds[ j ] ) ); - this.faceVertexUvs[ 0 ].push( [ - - new THREE.UV( 1 - r / this.angle, j / points.length ), - new THREE.UV( 1 - r / this.angle, ( j + 1 ) / points.length ), - new THREE.UV( 1 - ( r - stepSize ) / this.angle, ( j + 1 ) / points.length ), - new THREE.UV( 1 - ( r - stepSize ) / this.angle, j / points.length ) - - ] ); - - } - - oldInds = newInds; - newInds = []; - - } - - this.computeCentroids(); - this.computeFaceNormals(); - this.computeVertexNormals(); - -}; - -THREE.LatheGeometry.prototype = new THREE.Geometry(); -THREE.LatheGeometry.prototype.constructor = THREE.LatheGeometry; -/** - * @author mr.doob / http://mrdoob.com/ - * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Plane.as - */ - -THREE.PlaneGeometry = function ( width, height, segmentsWidth, segmentsHeight ) { - - THREE.Geometry.call( this ); - - var ix, iy, - width_half = width / 2, - height_half = height / 2, - gridX = segmentsWidth || 1, - gridY = segmentsHeight || 1, - gridX1 = gridX + 1, - gridY1 = gridY + 1, - segment_width = width / gridX, - segment_height = height / gridY; - - - for( iy = 0; iy < gridY1; iy++ ) { - - for( ix = 0; ix < gridX1; ix++ ) { - - var x = ix * segment_width - width_half; - var y = iy * segment_height - height_half; - - this.vertices.push( new THREE.Vertex( new THREE.Vector3( x, - y, 0 ) ) ); - - } - - } - - for( iy = 0; iy < gridY; iy++ ) { - - for( ix = 0; ix < gridX; ix++ ) { - - var a = ix + gridX1 * iy; - var b = ix + gridX1 * ( iy + 1 ); - var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); - var d = ( ix + 1 ) + gridX1 * iy; - - this.faces.push( new THREE.Face4( a, b, c, d ) ); - this.faceVertexUvs[ 0 ].push( [ - new THREE.UV( ix / gridX, iy / gridY ), - new THREE.UV( ix / gridX, ( iy + 1 ) / gridY ), - new THREE.UV( ( ix + 1 ) / gridX, ( iy + 1 ) / gridY ), - new THREE.UV( ( ix + 1 ) / gridX, iy / gridY ) - ] ); - - } - - } - - this.computeCentroids(); - this.computeFaceNormals(); - -}; - -THREE.PlaneGeometry.prototype = new THREE.Geometry(); -THREE.PlaneGeometry.prototype.constructor = THREE.PlaneGeometry; -/** - * @author mr.doob / http://mrdoob.com/ - * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Sphere.as - */ - -THREE.SphereGeometry = function ( radius, segmentsWidth, segmentsHeight ) { - - THREE.Geometry.call( this ); - - var radius = radius || 50, - gridX = segmentsWidth || 8, - gridY = segmentsHeight || 6; - - var i, j, pi = Math.PI; - var iHor = Math.max( 3, gridX ); - var iVer = Math.max( 2, gridY ); - var aVtc = []; - - for ( j = 0; j < ( iVer + 1 ) ; j++ ) { - - var fRad1 = j / iVer; - var fZ = radius * Math.cos( fRad1 * pi ); - var fRds = radius * Math.sin( fRad1 * pi ); - var aRow = []; - var oVtx = 0; - - for ( i = 0; i < iHor; i++ ) { - - var fRad2 = 2 * i / iHor; - var fX = fRds * Math.sin( fRad2 * pi ); - var fY = fRds * Math.cos( fRad2 * pi ); - - if ( !( ( j == 0 || j == iVer ) && i > 0 ) ) { - - oVtx = this.vertices.push( new THREE.Vertex( new THREE.Vector3( fY, fZ, fX ) ) ) - 1; - - } - - aRow.push( oVtx ); - - } - - aVtc.push( aRow ); - - } - - var n1, n2, n3, iVerNum = aVtc.length; - - for ( j = 0; j < iVerNum; j++ ) { - - var iHorNum = aVtc[ j ].length; - - if ( j > 0 ) { - - for ( i = 0; i < iHorNum; i++ ) { - - var bEnd = i == ( iHorNum - 1 ); - var aP1 = aVtc[ j ][ bEnd ? 0 : i + 1 ]; - var aP2 = aVtc[ j ][ ( bEnd ? iHorNum - 1 : i ) ]; - var aP3 = aVtc[ j - 1 ][ ( bEnd ? iHorNum - 1 : i ) ]; - var aP4 = aVtc[ j - 1 ][ bEnd ? 0 : i + 1 ]; - - var fJ0 = j / ( iVerNum - 1 ); - var fJ1 = ( j - 1 ) / ( iVerNum - 1 ); - var fI0 = ( i + 1 ) / iHorNum; - var fI1 = i / iHorNum; - - var aP1uv = new THREE.UV( 1 - fI0, fJ0 ); - var aP2uv = new THREE.UV( 1 - fI1, fJ0 ); - var aP3uv = new THREE.UV( 1 - fI1, fJ1 ); - var aP4uv = new THREE.UV( 1 - fI0, fJ1 ); - - if ( j < ( aVtc.length - 1 ) ) { - - n1 = this.vertices[ aP1 ].position.clone(); - n2 = this.vertices[ aP2 ].position.clone(); - n3 = this.vertices[ aP3 ].position.clone(); - n1.normalize(); - n2.normalize(); - n3.normalize(); - - this.faces.push( new THREE.Face3( aP1, aP2, aP3, [ new THREE.Vector3( n1.x, n1.y, n1.z ), new THREE.Vector3( n2.x, n2.y, n2.z ), new THREE.Vector3( n3.x, n3.y, n3.z ) ] ) ); - - this.faceVertexUvs[ 0 ].push( [ aP1uv, aP2uv, aP3uv ] ); - - } - - if ( j > 1 ) { - - n1 = this.vertices[aP1].position.clone(); - n2 = this.vertices[aP3].position.clone(); - n3 = this.vertices[aP4].position.clone(); - n1.normalize(); - n2.normalize(); - n3.normalize(); - - this.faces.push( new THREE.Face3( aP1, aP3, aP4, [ new THREE.Vector3( n1.x, n1.y, n1.z ), new THREE.Vector3( n2.x, n2.y, n2.z ), new THREE.Vector3( n3.x, n3.y, n3.z ) ] ) ); - - this.faceVertexUvs[ 0 ].push( [ aP1uv, aP3uv, aP4uv ] ); - - } - - } - } - } - - this.computeCentroids(); - this.computeFaceNormals(); - this.computeVertexNormals(); - - this.boundingSphere = { radius: radius }; - -}; - -THREE.SphereGeometry.prototype = new THREE.Geometry(); -THREE.SphereGeometry.prototype.constructor = THREE.SphereGeometry; -/** - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author alteredq / http://alteredqualia.com/ - * - * For creating 3D text geometry in three.js - * - * Text = 3D Text - * - * parameters = { - * size: , // size of the text - * height: , // thickness to extrude text - * curveSegments: , // number of points on the curves - * - * font: , // font name - * weight: , // font weight (normal, bold) - * style: , // font style (normal, italics) - * - * bezelEnabled: , // turn on bezel - * bezelThickness: , // how deep into text bezel goes - * bezelSize: , // how far from text outline is bezel - * } - * - * It uses techniques used in - * - * typeface.js and canvastext - * For converting fonts and rendering with javascript - * http://typeface.neocracy.org - * - * Triangulation ported from AS3 - * Simple Polygon Triangulation - * http://actionsnippet.com/?p=1462 - * - * A Method to triangulate shapes with holes - * http://www.sakri.net/blog/2009/06/12/an-approach-to-triangulating-polygons-with-holes/ - * - */ - -THREE.TextGeometry = function ( text, parameters ) { - - THREE.Geometry.call( this ); - - this.parameters = parameters || {}; - this.set( text ); - -}; - -THREE.TextGeometry.prototype = new THREE.Geometry(); -THREE.TextGeometry.prototype.constructor = THREE.TextGeometry; - -THREE.TextGeometry.prototype.set = function ( text, parameters ) { - - this.text = text; - var parameters = parameters || this.parameters; - - var size = parameters.size !== undefined ? parameters.size : 100; - var height = parameters.height !== undefined ? parameters.height : 50; - var curveSegments = parameters.curveSegments !== undefined ? parameters.curveSegments: 4; - - var font = parameters.font !== undefined ? parameters.font : "helvetiker"; - var weight = parameters.weight !== undefined ? parameters.weight : "normal"; - var style = parameters.style !== undefined ? parameters.style : "normal"; - - var bezelThickness = parameters.bezelThickness !== undefined ? parameters.bezelThickness : 10; - var bezelSize = parameters.bezelSize !== undefined ? parameters.bezelSize : 8; - var bezelEnabled = parameters.bezelEnabled !== undefined ? parameters.bezelEnabled : false; - - THREE.FontUtils.size = size; - THREE.FontUtils.divisions = curveSegments; - - THREE.FontUtils.face = font; - THREE.FontUtils.weight = weight; - THREE.FontUtils.style = style; - - THREE.FontUtils.bezelSize = bezelSize; - - // Get a Font data json object - - var data = THREE.FontUtils.drawText( text ); - - //console.log("data", data); - - var vertices = data.points; - var faces = data.faces; - var contour = data.contour; - var bezelPoints = data.bezel; - - var scope = this; - - scope.vertices = []; - scope.faces = []; - - //console.log(this); - - var i, - vert, vlen = vertices.length, - face, flen = faces.length, - bezelPt, blen = bezelPoints.length; - - // Back facing vertices - - for ( i = 0; i < vlen; i++ ) { - - vert = vertices[ i ]; - v( vert.x, vert.y, 0 ); - - } - - // Front facing vertices - - for ( i = 0; i < vlen; i++ ) { - - vert = vertices[ i ]; - v( vert.x, vert.y, height ); - - } - - if ( bezelEnabled ) { - - for ( i = 0; i < blen; i++ ) { - - bezelPt = bezelPoints[ i ]; - v( bezelPt.x, bezelPt.y, bezelThickness ); - - } - - for ( i = 0; i < blen; i++ ) { - - bezelPt = bezelPoints[ i ]; - v( bezelPt.x, bezelPt.y, height - bezelThickness ); - - } - - } - - // Bottom faces - - for ( i = 0; i < flen; i++ ) { - - face = faces[ i ]; - f3( face[ 2 ], face[ 1 ], face[ 0 ] ); - - } - - // Top faces - - for ( i = 0; i < flen; i++ ) { - - face = faces[ i ]; - f3( face[ 0 ] + vlen, face[ 1 ] + vlen, face[ 2 ] + vlen ); - - } - - var lastV; - var j, k, l, m; - - if ( bezelEnabled ) { - - i = bezelPoints.length; - - while ( --i > 0 ) { - - if ( !lastV ) { - - lastV = contour[ i ]; - - } else if ( lastV.equals( contour[ i ] ) ) { - - // We reached the last point of a closed loop - - lastV = null; - continue; - - } - - l = vlen * 2 + i; - m = l - 1; - - // Create faces for the z-sides of the text - - f4( l, m, m + blen, l + blen ); - - for ( j = 0; j < vlen; j++ ) { - - if ( vertices[ j ].equals( contour[ i ] ) ) break; - - } - - for ( k = 0; k < vlen; k++ ) { - - if ( vertices[ k ].equals( contour[ i - 1 ] ) ) break; - - } - - // Create faces for the z-sides of the text - - f4( j, k, m, l ); - f4( l + blen, m + blen, k + vlen, j + vlen ); - - } - - } else { - - i = contour.length; - - while ( --i > 0 ) { - - if ( !lastV ) { - - lastV = contour[ i ]; - - } else if ( lastV.equals( contour[ i ] ) ) { - - // We reached the last point of a closed loop - - lastV = null; - continue; - - } - - for ( j = 0; j < vlen; j++ ) { - - if ( vertices[ j ].equals( contour[ i ] ) ) break; - - } - - for ( k = 0; k < vlen; k++ ) { - - if ( vertices[ k ].equals( contour[ i - 1 ] ) ) break; - - } - - // Create faces for the z-sides of the text - - f4( j, k, k + vlen, j + vlen ); - - } - } - - - // UVs to be added - - this.computeCentroids(); - this.computeFaceNormals(); - //this.computeVertexNormals(); - - function v( x, y, z ) { - - scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) ); - - } - - function f3( a, b, c ) { - - scope.faces.push( new THREE.Face3( a, b, c) ); - - } - - function f4( a, b, c, d ) { - - scope.faces.push( new THREE.Face4( a, b, c, d) ); - - } - - -}; - -THREE.FontUtils = { - - faces : {}, - - // Just for now. face[weight][style] - - face : "helvetiker", - weight: "normal", - style : "normal", - size : 150, - divisions : 10, - - getFace : function() { - - return this.faces[ this.face ][ this.weight ][ this.style ]; - - }, - - loadFace : function( data ) { - - var family = data.familyName.toLowerCase(); - - var ThreeFont = this; - - ThreeFont.faces[ family ] = ThreeFont.faces[ family ] || {}; - - ThreeFont.faces[ family ][ data.cssFontWeight ] = ThreeFont.faces[ family ][ data.cssFontWeight ] || {}; - ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data; - - var face = ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data; - - return data; - - }, - - - extractPoints : function( points, characters ) { - - // Quick exit - - if ( points.length < 3 ) { - - //throw "not valid polygon"; - - console.log( "not valid polygon" ); - - return { - - points: points, - faces: [] - - }; - - } - - // Try to split shapes and holes. - - var p, point, shape, - all, - isolatedShapes = []; - - // Use a quick hashmap for locating duplicates - - for ( var c in characters ) { - - points = characters[ c ]; - - - all = []; - - // Use a quick hashmap for locating duplicates - - for ( var p in points ) { - - point = points[ p ]; - all.push( point.x + "," + point.y ); - - } - - var firstIndex, firstPt, endPt, holes; - - // We check the first loop whether its CW or CCW direction to determine - // whether its shapes or holes first - - endPt = all.slice(1).indexOf( all[0] ); - var shapesFirst = this.Triangulate.area( points.slice( 0, endPt + 1 ) ) < 0; - - //console.log(points.length, "shapesFirst",shapesFirst); - - holes = []; - endPt = -1; - - while ( endPt < all.length ) { - - firstIndex = endPt + 1; - firstPt = all[ firstIndex ]; - endPt = all.slice( firstIndex + 1 ).indexOf( firstPt ) + firstIndex; - - if ( endPt <= firstIndex ) break; - - var contours = points.slice( firstIndex, endPt + 1 ); - - if ( shapesFirst ) { - - if ( this.Triangulate.area( contours ) < 0 ) { - - // we got new isolated shape - - if ( firstIndex > 0 ) { - - isolatedShapes.push( { shape: shape, holes: holes } ); - - } - - // Save the old shapes, then work on new additional separated shape - - shape = contours; - holes = []; - - } else { - - holes.push( contours ); - - } - - } else { - - if ( this.Triangulate.area( contours ) < 0 ) { - - isolatedShapes.push( {shape: contours, holes: holes } ); - holes = []; - - } else { - - holes.push( contours ); - - } - - } - - endPt++; - - } - - if ( shapesFirst ) { - - isolatedShapes.push( { shape: shape, holes: holes } ); - - } - - } - - //console.log("isolatedShapes", isolatedShapes); - - /* For each isolated shape, find the closest points and break to the hole to allow triangulation*/ - - // Find closest points between holes - - // we could optimize with - // http://en.wikipedia.org/wiki/Proximity_problems - // http://en.wikipedia.org/wiki/Closest_pair_of_points - // http://stackoverflow.com/questions/1602164/shortest-distance-between-points-algorithm - - var prevShapeVert, nextShapeVert, - prevHoleVert, nextHoleVert, - holeIndex, shapeIndex, - shapeId, shapeGroup, - h, h2, - hole, shortest, d, - p, pts1, pts2, - tmpShape1, tmpShape2, - tmpHole1, tmpHole2, - verts = []; - - for ( shapeId = 0; shapeId < isolatedShapes.length; shapeId ++ ) { - - shapeGroup = isolatedShapes[ shapeId ]; - - shape = shapeGroup.shape; - holes = shapeGroup.holes; - - for ( h = 0; h < holes.length; h++ ) { - - // we slice to each hole when neccessary - - hole = holes[ h ]; - shortest = Number.POSITIVE_INFINITY; - - for ( h2 = 0; h2 < hole.length; h2++ ) { - - pts1 = hole[ h2 ]; - - for ( p = 0; p < shape.length; p++ ) { - - pts2 = shape[ p ]; - d = pts1.distanceTo( pts2 ); - - if ( d < shortest ) { - - shortest = d; - holeIndex = h2; - shapeIndex = p; - - } - - } - - } - - prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1; - nextShapeVert = ( shapeIndex + 1 ) < shape.length ? shapeIndex + 1 : 0; - - prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1; - nextHoleVert = ( holeIndex + 1 ) < hole.length ? holeIndex + 1 : 0 ; - - var areaapts = []; - areaapts.push( hole[ holeIndex ] ); - areaapts.push( shape[ shapeIndex ] ); - areaapts.push( shape[ prevShapeVert ] ); - - var areaa = this.Triangulate.area( areaapts ); - - var areabpts = []; - areabpts.push( hole[ holeIndex ] ); - areabpts.push( hole[ prevHoleVert ] ); - areabpts.push( shape[ shapeIndex ] ); - - var areab = this.Triangulate.area( areabpts ); - - var shapeOffset =1; - var holeOffset = -1; - - var oldShapeIndex = shapeIndex, oldHoleIndex = holeIndex; - shapeIndex += shapeOffset; - holeIndex += holeOffset; - - if ( shapeIndex < 0 ) { shapeIndex += shape.length; } - shapeIndex %= shape.length; - - if ( holeIndex < 0 ) { holeIndex += hole.length; } - holeIndex %= shape.length; - - prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1; - nextShapeVert = ( shapeIndex + 1 ) < shape.length ? shapeIndex + 1 : 0; - - prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1; - nextHoleVert = ( holeIndex + 1 ) < hole.length ? holeIndex + 1 : 0 ; - - - areaapts = []; - areaapts.push( hole[ holeIndex ] ); - areaapts.push( shape[ shapeIndex ] ); - areaapts.push( shape[ prevShapeVert ] ); - - var areaa2 = this.Triangulate.area( areaapts ); - - areabpts = []; - areabpts.push( hole[ holeIndex ] ); - areabpts.push( hole[ prevHoleVert ] ); - areabpts.push( shape[ shapeIndex ] ); - - var areab2 = this.Triangulate.area( areabpts ); - - if ( ( areaa + areab ) > ( areaa2 + areab2 ) ) { - - shapeIndex = oldShapeIndex; - holeIndex = oldHoleIndex ; - - if ( shapeIndex < 0 ) { shapeIndex += shape.length; } - shapeIndex %= shape.length; - - if ( holeIndex < 0 ) { holeIndex += hole.length; } - holeIndex %= shape.length; - - - prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1; - nextShapeVert = ( shapeIndex + 1 ) < shape.length ? shapeIndex + 1 : 0; - - prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1; - nextHoleVert = ( holeIndex + 1 ) < hole.length ? holeIndex + 1 : 0 ; - - } - - tmpShape1 = shape.slice( 0, shapeIndex ); - tmpShape2 = shape.slice( shapeIndex ); - tmpHole1 = hole.slice( holeIndex ); - tmpHole2 = hole.slice( 0, holeIndex ); - - verts.push( hole[ holeIndex ] ); - verts.push( shape[ shapeIndex ] ); - verts.push( shape[ prevShapeVert ] ); - - verts.push( hole[ holeIndex ] ); - verts.push( hole[ prevHoleVert ] ); - verts.push( shape[ shapeIndex ] ); - - shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 ); - - } - - shapeGroup.shape = shape; - - } - - var points = []; - var triangulatedVertices = []; - var lastTriangles = 0; - - for ( shapeId = 0; shapeId < isolatedShapes.length; shapeId ++ ) { - - shapeGroup = isolatedShapes[ shapeId ]; - - shape = shapeGroup.shape; - points = points.concat( shape ); - - var triangles = THREE.FontUtils.Triangulate( shape, true ); - - // We need to offset vertex indices for faces - - for ( var v = 0; v < triangles.length; v++ ) { - - var face = triangles[ v ]; - - face[ 0 ] += lastTriangles; - face[ 1 ] += lastTriangles; - face[ 2 ] += lastTriangles; - - } - - triangulatedVertices = triangulatedVertices.concat( triangles ); - lastTriangles += shape.length; - - } - - - // Now we push the "cut" vertices back to the triangulated indices. - - //console.log("we have verts.length",verts.length,verts); - - var v, j, k, l, found, face; - - for ( v = 0; v < verts.length / 3; v++ ) { - - face = []; - - for ( k = 0; k < 3; k++ ) { - - found = false; - - for ( j=0; j < points.length && !found; j++ ) { - - l = v * 3 + k; - - if ( points[ j ].equals( verts[ l ] ) ) { - - face.push( j ); - found = true; - - } - - } - - // you would not wish to reach this point of code, something went wrong - - if ( !found ) { - - points.push( verts[ l ] ); - face.push( points.length - 1 ); - - console.log( "not found" ) - - } - - } - - triangulatedVertices.push( face ); - - } - - - //console.log("triangles", triangulatedVertices.length, "points", points); - - return { - - points: points, - faces: triangulatedVertices - - }; - - }, - - drawText : function( text ) { - - var characterpts = [], pts = []; - - // RenderText - - var i, p, - face = this.getFace(), - scale = this.size / face.resolution, - offset = 0, - chars = String( text ).split( '' ), - length = chars.length; - - for ( i = 0; i < length; i++ ) { - - var ret = this.extractGlyphPoints( chars[ i ], face, scale, offset ); - offset += ret.offset; - characterpts.push(ret.points); - pts = pts.concat(ret.points); - - } - - // get the width - - var width = offset / 2; - - for ( p = 0; p < pts.length; p++ ) { - - pts[ p ].x -= width; - - } - - var extract = this.extractPoints( pts, characterpts ); - - extract.contour = pts; - - var bezelPoints = []; - - var centroids = [], forCentroids = [], expandOutwards = [], sum = new THREE.Vector2(), lastV; - - i = pts.length; - - while ( --i >= 0 ) { - - if ( !lastV ) { - - lastV = pts[ i ]; - - } else if ( lastV.equals( pts[ i ] ) ) { - - // We reached the last point of a closed loop - - lastV = null; - - var bool = this.Triangulate.area( forCentroids ) > 0; - expandOutwards.push( bool ); - centroids.push( sum.divideScalar( forCentroids.length ) ); - forCentroids = []; - - sum = new THREE.Vector2(); - continue; - - } - - sum.addSelf( pts[ i ] ); - forCentroids.push( pts[ i ] ); - - } - - - i = pts.length; - p = 0; - var pt, centroid ; - var dirV, adj; - - while ( --i >= 0 ) { - - pt = pts[ i ]; - centroid = centroids[p]; - - dirV = pt.clone().subSelf( centroid) ; - adj = this.bezelSize / dirV.length(); - - if ( expandOutwards[ p ] ) { - - adj += 1; - - } else { - - adj = 1 - adj; - - } - - adj = dirV.multiplyScalar( adj ).addSelf( centroid ); - bezelPoints.unshift( adj ); - - - if ( !lastV ) { - - lastV = pts[ i ]; - - } else if ( lastV.equals( pts[ i ] ) ) { - - // We reached the last point of a closed loop - - lastV = null; - p++; - continue; - - } - - } - - - /* - for ( p = 0; p < pts.length; p++ ) { - pt = pts[ p ]; - bezelPoints.push (new THREE.Vector2(pt.x + this.bezelSize, pt.y + this.bezelSize)); - - }*/ - - extract.bezel = bezelPoints; - - return extract; - - }, - - - // Bezier Curves formulas obtained from - // http://en.wikipedia.org/wiki/B%C3%A9zier_curve - - // Quad Bezier Functions - - b2p0: function ( t, p ) { - - var k = 1 - t; - return k * k * p; - - }, - - b2p1: function ( t, p ) { - - return 2 * ( 1 - t ) * t * p; - - }, - - b2p2: function ( t, p ) { - - return t * t * p; - - }, - - b2: function ( t, p0, p1, p2 ) { - - return this.b2p0( t, p0 ) + this.b2p1( t, p1 ) + this.b2p2( t, p2 ); - - }, - - // Cubic Bezier Functions - - b3p0: function ( t, p ) { - - var k = 1 - t; - return k * k * k * p; - - }, - - b3p1: function ( t, p ) { - - var k = 1 - t; - return 3 * k * k * t * p; - - }, - - b3p2: function ( t, p ) { - - var k = 1 - t; - return 3 * k * t * t * p; - - }, - - b3p3: function ( t, p ) { - - return t * t * t * p; - - }, - - b3: function ( t, p0, p1, p2, p3 ) { - - return this.b3p0( t, p0 ) + this.b3p1( t, p1 ) + this.b3p2( t, p2 ) + this.b3p3( t, p3 ); - - }, - - - extractGlyphPoints : function( c, face, scale, offset ) { - - var pts = []; - - var i, i2, - outline, action, length, - scaleX, scaleY, - x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2, - laste, - glyph = face.glyphs[ c ] || face.glyphs[ ctxt.options.fallbackCharacter ]; - - if ( !glyph ) return; - - if ( glyph.o ) { - - outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) ); - length = outline.length; - - scaleX = scale; - scaleY = scale; - - for ( i = 0; i < length; ) { - - action = outline[ i++ ]; - - switch( action ) { - - case 'm': - - // Move To - - x = outline[ i++ ] * scaleX + offset; - y = outline[ i++ ] * scaleY; - pts.push( new THREE.Vector2( x, y ) ); - break; - - case 'l': - - // Line To - - x = outline[ i++ ] * scaleX + offset; - y = outline[ i++ ] * scaleY; - pts.push( new THREE.Vector2( x, y ) ); - break; - - case 'q': - - // QuadraticCurveTo - - cpx = outline[ i++ ] * scaleX + offset; - cpy = outline[ i++ ] * scaleY; - cpx1 = outline[ i++ ] * scaleX + offset; - cpy1 = outline[ i++ ] * scaleY; - - laste = pts[ pts.length - 1 ]; - - if ( laste ) { - - cpx0 = laste.x; - cpy0 = laste.y; - - for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2++ ) { - - var t = i2 / divisions; - var tx = THREE.FontUtils.b2( t, cpx0, cpx1, cpx ); - var ty = THREE.FontUtils.b2( t, cpy0, cpy1, cpy ); - pts.push( new THREE.Vector2( tx, ty ) ); - - } - - } - - break; - - case 'b': - - // Cubic Bezier Curve - - cpx = outline[ i++ ] * scaleX + offset; - cpy = outline[ i++ ] * scaleY; - cpx1 = outline[ i++ ] * scaleX + offset; - cpy1 = outline[ i++ ] * -scaleY; - cpx2 = outline[ i++ ] * scaleX + offset; - cpy2 = outline[ i++ ] * -scaleY; - - laste = pts[ pts.length - 1 ]; - - if ( laste ) { - - cpx0 = laste.x; - cpy0 = laste.y; - - for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2++ ) { - - var t = i2 / divisions; - var tx = THREE.FontUtils.b3( t, cpx0, cpx1, cpx2, cpx ); - var ty = THREE.FontUtils.b3( t, cpy0, cpy1, cpy2, cpy ); - pts.push( new THREE.Vector2( tx, ty ) ); - - } - - } - - break; - - } - - } - } - - return { offset: glyph.ha*scale, points:pts }; - } - -}; - - - -/** - * This code is a quick port of code written in C++ which was submitted to - * flipcode.com by John W. Ratcliff // July 22, 2000 - * See original code and more information here: - * http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml - * - * ported to actionscript by Zevan Rosser - * www.actionsnippet.com - * - * ported to javascript by Joshua Koo - * http://www.lab4games.net/zz85/blog - * - */ - - -( function( namespace ) { - - var EPSILON = 0.0000000001; - - // takes in an contour array and returns - - var process = function( contour, indices ) { - - var n = contour.length; - - if ( n < 3 ) return null; - - var result = [], - verts = [], - vertIndices = []; - - /* we want a counter-clockwise polygon in verts */ - - var u, v, w; - - if ( area( contour ) > 0.0 ) { - - for ( v = 0; v < n; v++ ) verts[ v ] = v; - - } else { - - for ( v = 0; v < n; v++ ) verts[ v ] = ( n - 1 ) - v; - - } - - var nv = n; - - /* remove nv - 2 vertices, creating 1 triangle every time */ - - var count = 2 * nv; /* error detection */ - - for( v = nv - 1; nv > 2; ) { - - /* if we loop, it is probably a non-simple polygon */ - - if ( ( count-- ) <= 0 ) { - - //** Triangulate: ERROR - probable bad polygon! - - //throw ( "Warning, unable to triangulate polygon!" ); - //return null; - - console.log( "Warning, unable to triangulate polygon!" ); - - if ( indices ) return vertIndices; - return result; - - } - - /* three consecutive vertices in current polygon, */ - - u = v; if ( nv <= u ) u = 0; /* previous */ - v = u + 1; if ( nv <= v ) v = 0; /* new v */ - w = v + 1; if ( nv <= w ) w = 0; /* next */ - - if ( snip( contour, u, v, w, nv, verts ) ) { - - var a, b, c, s, t; - - /* true names of the vertices */ - - a = verts[ u ]; - b = verts[ v ]; - c = verts[ w ]; - - /* output Triangle */ - - result.push( contour[ a ] ); - result.push( contour[ b ] ); - result.push( contour[ c ] ); - - vertIndices.push( [ verts[ u ], verts[ v ], verts[ w ] ] ); - - /* remove v from the remaining polygon */ - - for( s = v, t = v + 1; t < nv; s++, t++ ) { - - verts[ s ] = verts[ t ]; - - } - - nv--; - - /* reset error detection counter */ - - count = 2 * nv; - - } - - } - - if ( indices ) return vertIndices; - return result; - - }; - - // calculate area of the contour polygon - - var area = function ( contour ) { - - var n = contour.length; - var a = 0.0; - - for( var p = n - 1, q = 0; q < n; p = q++ ) { - - a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y; - - } - - return a * 0.5; - - }; - - // see if p is inside triangle abc - - var insideTriangle = function( ax, ay, - bx, by, - cx, cy, - px, py ) { - - var aX, aY, bX, bY; - var cX, cY, apx, apy; - var bpx, bpy, cpx, cpy; - var cCROSSap, bCROSScp, aCROSSbp; - - aX = cx - bx; aY = cy - by; - bX = ax - cx; bY = ay - cy; - cX = bx - ax; cY = by - ay; - apx= px -ax; apy= py - ay; - bpx= px - bx; bpy= py - by; - cpx= px - cx; cpy= py - cy; - - aCROSSbp = aX*bpy - aY*bpx; - cCROSSap = cX*apy - cY*apx; - bCROSScp = bX*cpy - bY*cpx; - - return ( (aCROSSbp >= 0.0) && (bCROSScp >= 0.0) && (cCROSSap >= 0.0) ); - - }; - - - var snip = function ( contour, u, v, w, n, verts ) { - - var p; - var ax, ay, bx, by; - var cx, cy, px, py; - - ax = contour[ verts[ u ] ].x; - ay = contour[ verts[ u ] ].y; - - bx = contour[ verts[ v ] ].x; - by = contour[ verts[ v ] ].y; - - cx = contour[ verts[ w ] ].x; - cy = contour[ verts[ w ] ].y; - - if ( EPSILON > (((bx-ax)*(cy-ay)) - ((by-ay)*(cx-ax))) ) return false; - - for ( p = 0; p < n; p++ ) { - - if( (p == u) || (p == v) || (p == w) ) continue; - - px = contour[ verts[ p ] ].x - py = contour[ verts[ p ] ].y - - if ( insideTriangle( ax, ay, bx, by, cx, cy, px, py ) ) return false; - - } - - return true; - - }; - - - namespace.Triangulate = process; - namespace.Triangulate.area = area; - - return namespace; - -})(THREE.FontUtils); - -// To use the typeface.js face files, hook up the API -window._typeface_js = { faces: THREE.FontUtils.faces, loadFace: THREE.FontUtils.loadFace }; -/** - * @author oosmoxiecode - * based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3DLite/src/away3dlite/primitives/Torus.as?r=2888 - */ - -THREE.TorusGeometry = function ( radius, tube, segmentsR, segmentsT ) { - - THREE.Geometry.call( this ); - - var scope = this; - - this.radius = radius || 100; - this.tube = tube || 40; - this.segmentsR = segmentsR || 8; - this.segmentsT = segmentsT || 6; - - var temp_uv = []; - - for ( var j = 0; j <= this.segmentsR; ++j ) { - - for ( var i = 0; i <= this.segmentsT; ++i ) { - - var u = i / this.segmentsT * 2 * Math.PI; - var v = j / this.segmentsR * 2 * Math.PI; - var x = (this.radius + this.tube*Math.cos(v))*Math.cos(u); - var y = (this.radius + this.tube*Math.cos(v))*Math.sin(u); - var z = this.tube*Math.sin(v); - - vert( x, y, z ); - - temp_uv.push( [i/this.segmentsT, 1 - j/this.segmentsR] ); - - } - } - - - for ( var j = 1; j <= this.segmentsR; ++j ) { - - for ( var i = 1; i <= this.segmentsT; ++i ) { - - var a = (this.segmentsT + 1)*j + i; - var b = (this.segmentsT + 1)*j + i - 1; - var c = (this.segmentsT + 1)*(j - 1) + i - 1; - var d = (this.segmentsT + 1)*(j - 1) + i; - - f4( a, b, c,d ); - - this.faceVertexUvs[ 0 ].push( [new THREE.UV( temp_uv[a][0], temp_uv[a][1] ), - new THREE.UV( temp_uv[b][0], temp_uv[b][1] ), - new THREE.UV( temp_uv[c][0], temp_uv[c][1] ), - new THREE.UV( temp_uv[d][0], temp_uv[d][1] ) - ] ); - } - - } - - delete temp_uv; - - this.computeCentroids(); - this.computeFaceNormals(); - this.computeVertexNormals(); - - function vert( x, y, z ) { - - scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) ); - - }; - - function f4( a, b, c, d ) { - - scope.faces.push( new THREE.Face4( a, b, c, d ) ); - - }; - -}; - -THREE.TorusGeometry.prototype = new THREE.Geometry(); -THREE.TorusGeometry.prototype.constructor = THREE.TorusGeometry; -/** - * @author oosmoxiecode - * based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3D/src/away3d/primitives/TorusKnot.as?spec=svn2473&r=2473 - */ - -THREE.TorusKnotGeometry = function ( radius, tube, segmentsR, segmentsT, p, q, heightScale ) { - - THREE.Geometry.call( this ); - - var scope = this; - - this.radius = radius || 200; - this.tube = tube || 40; - this.segmentsR = segmentsR || 64; - this.segmentsT = segmentsT || 8; - this.p = p || 2; - this.q = q || 3; - this.heightScale = heightScale || 1; - this.grid = new Array(this.segmentsR); - - var tang = new THREE.Vector3(); - var n = new THREE.Vector3(); - var bitan = new THREE.Vector3(); - - for ( var i = 0; i < this.segmentsR; ++ i ) { - - this.grid[ i ] = new Array( this.segmentsT ); - - for ( var j = 0; j < this.segmentsT; ++ j ) { - - var u = i / this.segmentsR * 2 * this.p * Math.PI; - var v = j / this.segmentsT * 2 * Math.PI; - var p = getPos( u, v, this.q, this.p, this.radius, this.heightScale ); - var p2 = getPos( u + 0.01, v, this.q, this.p, this.radius, this.heightScale ); - var cx, cy; - - tang.x = p2.x - p.x; tang.y = p2.y - p.y; tang.z = p2.z - p.z; - n.x = p2.x + p.x; n.y = p2.y + p.y; n.z = p2.z + p.z; - bitan.cross( tang, n ); - n.cross( bitan, tang ); - bitan.normalize(); - n.normalize(); - - cx = - this.tube * Math.cos( v ); // TODO: Hack: Negating it so it faces outside. - cy = this.tube * Math.sin( v ); - - p.x += cx * n.x + cy * bitan.x; - p.y += cx * n.y + cy * bitan.y; - p.z += cx * n.z + cy * bitan.z; - - this.grid[ i ][ j ] = vert( p.x, p.y, p.z ); - - } - - } - - for ( var i = 0; i < this.segmentsR; ++ i ) { - - for ( var j = 0; j < this.segmentsT; ++ j ) { - - var ip = ( i + 1 ) % this.segmentsR; - var jp = ( j + 1 ) % this.segmentsT; - var a = this.grid[ i ][ j ]; - var b = this.grid[ ip ][ j ]; - var c = this.grid[ ip ][ jp ]; - var d = this.grid[ i ][ jp ]; - - var uva = new THREE.UV( i / this.segmentsR, j / this.segmentsT ); - var uvb = new THREE.UV( ( i + 1 ) / this.segmentsR, j / this.segmentsT ); - var uvc = new THREE.UV( ( i + 1 ) / this.segmentsR, ( j + 1 ) / this.segmentsT ); - var uvd = new THREE.UV( i / this.segmentsR, ( j + 1 ) / this.segmentsT ); - - this.faces.push( new THREE.Face4( a, b, c, d ) ); - this.faceVertexUvs[ 0 ].push( [ uva,uvb,uvc, uvd ] ); - - } - } - - this.computeCentroids(); - this.computeFaceNormals(); - this.computeVertexNormals(); - - function vert( x, y, z ) { - - return scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) ) - 1; - - } - - function getPos( u, v, in_q, in_p, radius, heightScale ) { - - var cu = Math.cos( u ); - var cv = Math.cos( v ); - var su = Math.sin( u ); - var quOverP = in_q / in_p * u; - var cs = Math.cos( quOverP ); - - var tx = radius * ( 2 + cs ) * 0.5 * cu; - var ty = radius * ( 2 + cs ) * su * 0.5; - var tz = heightScale * radius * Math.sin( quOverP ) * 0.5; - - return new THREE.Vector3( tx, ty, tz ); - - } - -}; - -THREE.TorusKnotGeometry.prototype = new THREE.Geometry(); -THREE.TorusKnotGeometry.prototype.constructor = THREE.TorusKnotGeometry; -/** - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.Loader = function ( showStatus ) { - - this.showStatus = showStatus; - this.statusDomElement = showStatus ? THREE.Loader.prototype.addStatusElement() : null; - - this.onLoadStart = function () {}; - this.onLoadProgress = function() {}; - this.onLoadComplete = function () {}; - -}; - -THREE.Loader.prototype = { - - addStatusElement: function () { - - var e = document.createElement( "div" ); - - e.style.position = "absolute"; - e.style.right = "0px"; - e.style.top = "0px"; - e.style.fontSize = "0.8em"; - e.style.textAlign = "left"; - e.style.background = "rgba(0,0,0,0.25)"; - e.style.color = "#fff"; - e.style.width = "120px"; - e.style.padding = "0.5em 0.5em 0.5em 0.5em"; - e.style.zIndex = 1000; - - e.innerHTML = "Loading ..."; - - return e; - - }, - - updateProgress: function ( progress ) { - - var message = "Loaded "; - - if ( progress.total ) { - - message += ( 100 * progress.loaded / progress.total ).toFixed(0) + "%"; - - - } else { - - message += ( progress.loaded / 1000 ).toFixed(2) + " KB"; - - } - - this.statusDomElement.innerHTML = message; - - }, - - extractUrlbase: function( url ) { - - var chunks = url.split( "/" ); - chunks.pop(); - return chunks.join( "/" ); - - }, - - init_materials: function( scope, materials, texture_path ) { - - scope.materials = []; - - for ( var i = 0; i < materials.length; ++i ) { - - scope.materials[ i ] = [ THREE.Loader.prototype.createMaterial( materials[ i ], texture_path ) ]; - - } - - }, - - createMaterial: function ( m, texture_path ) { - - function is_pow2( n ) { - - var l = Math.log( n ) / Math.LN2; - return Math.floor( l ) == l; - - } - - function nearest_pow2( n ) { - - var l = Math.log( n ) / Math.LN2; - return Math.pow( 2, Math.round( l ) ); - - } - - function load_image( where, url ) { - - var image = new Image(); - - image.onload = function () { - - if ( !is_pow2( this.width ) || !is_pow2( this.height ) ) { - - var w = nearest_pow2( this.width ), - h = nearest_pow2( this.height ); - - where.image.width = w; - where.image.height = h; - where.image.getContext("2d").drawImage( this, 0, 0, w, h ); - - } else { - - where.image = this; - - } - - where.needsUpdate = true; - - }; - - image.src = url; - - } - - var material, mtype, mpars, texture, color, vertexColors; - - // defaults - - mtype = "MeshLambertMaterial"; - - // vertexColors - - mpars = { color: 0xeeeeee, opacity: 1.0, map: null, lightMap: null, wireframe: m.wireframe }; - - // parameters from model file - - if ( m.shading ) { - - if ( m.shading == "Phong" ) mtype = "MeshPhongMaterial"; - else if ( m.shading == "Basic" ) mtype = "MeshBasicMaterial"; - - } - - if ( m.blending ) { - - if ( m.blending == "Additive" ) mpars.blending = THREE.AdditiveBlending; - else if ( m.blending == "Subtractive" ) mpars.blending = THREE.SubtractiveBlending; - else if ( m.blending == "Multiply" ) mpars.blending = THREE.MultiplyBlending; - - } - - if ( m.transparent !== undefined || m.opacity < 1.0 ) { - - mpars.transparent = m.transparent; - - } - - if ( m.depthTest !== undefined ) { - - mpars.depthTest = m.depthTest; - - } - - if ( m.vertexColors !== undefined ) { - - if ( m.vertexColors == "face" ) { - - mpars.vertexColors = THREE.FaceColors; - - } else if ( m.vertexColors ) { - - mpars.vertexColors = THREE.VertexColors; - - } - - } - - if ( m.mapDiffuse && texture_path ) { - - texture = document.createElement( 'canvas' ); - - mpars.map = new THREE.Texture( texture ); - mpars.map.sourceFile = m.mapDiffuse; - - if( m.mapDiffuseRepeat ) { - - mpars.map.repeat.set( m.mapDiffuseRepeat[ 0 ], m.mapDiffuseRepeat[ 1 ] ); - mpars.map.wrapS = mpars.map.wrapT = THREE.RepeatWrapping; - - } - - if( m.mapDiffuseOffset ) { - - mpars.map.offset.set( m.mapDiffuseOffset[ 0 ], m.mapDiffuseOffset[ 1 ] ); - - } - - load_image( mpars.map, texture_path + "/" + m.mapDiffuse ); - - } else if ( m.colorDiffuse ) { - - color = ( m.colorDiffuse[0] * 255 << 16 ) + ( m.colorDiffuse[1] * 255 << 8 ) + m.colorDiffuse[2] * 255; - mpars.color = color; - mpars.opacity = m.transparency; - - } else if ( m.DbgColor ) { - - mpars.color = m.DbgColor; - - } - - if ( m.mapLight && texture_path ) { - - texture = document.createElement( 'canvas' ); - - mpars.lightMap = new THREE.Texture( texture ); - mpars.lightMap.sourceFile = m.mapLight; - - if( m.mapLightmapRepeat ) { - - mpars.lightMap.repeat.set( m.mapLightRepeat[ 0 ], m.mapLightRepeat[ 1 ] ); - mpars.lightMap.wrapS = mpars.lightMap.wrapT = THREE.RepeatWrapping; - - } - - if( m.mapLightmapOffset ) { - - mpars.lightMap.offset.set( m.mapLightmapOffset[ 0 ], m.mapLightmapOffset[ 1 ] ); - - } - - load_image( mpars.lightMap, texture_path + "/" + m.mapLightmap ); - - } - - material = new THREE[ mtype ]( mpars ); - - return material; - - } - -}; -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.JSONLoader = function ( showStatus ) { - - THREE.Loader.call( this, showStatus ); - -}; - -THREE.JSONLoader.prototype = new THREE.Loader(); -THREE.JSONLoader.prototype.constructor = THREE.JSONLoader; -THREE.JSONLoader.prototype.supr = THREE.Loader.prototype; - - -/** - * Load models generated by slim OBJ converter with ASCII option (converter_obj_three_slim.py -t ascii) - * - parameters - * - model (required) - * - callback (required) - * - texture_path (optional: if not specified, textures will be assumed to be in the same folder as JS model file) - */ - -THREE.JSONLoader.prototype.load = function ( parameters ) { - - var scope = this, - url = parameters.model, - callback = parameters.callback, - texture_path = parameters.texture_path ? parameters.texture_path : this.extractUrlbase( url ), - worker = new Worker( url ); - - worker.onmessage = function ( event ) { - - scope.createModel( event.data, callback, texture_path ); - scope.onLoadComplete(); - - }; - - this.onLoadStart(); - worker.postMessage( new Date().getTime() ); - -}; - -THREE.JSONLoader.prototype.createModel = function ( json, callback, texture_path ) { - - var scope = this, - geometry = new THREE.Geometry(), - scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0; - - this.init_materials( geometry, json.materials, texture_path ); - - parseModel( scale ); - - parseSkin(); - parseMorphing( scale ); - parseEdges(); - - geometry.computeCentroids(); - geometry.computeFaceNormals(); - - // geometry.computeEdgeFaces(); - - function parseModel( scale ) { - - if ( json.version === undefined || json.version != 2 ) { - - console.error( 'Deprecated file format.' ); - return; - - } - - function isBitSet( value, position ) { - - return value & ( 1 << position ); - - }; - - var i, j, fi, - - offset, zLength, nVertices, - - colorIndex, normalIndex, uvIndex, materialIndex, - - type, - isQuad, - hasMaterial, - hasFaceUv, hasFaceVertexUv, - hasFaceNormal, hasFaceVertexNormal, - hasFaceColor, hasFaceVertexColor, - - vertex, face, color, normal, - - uvLayer, uvs, u, v, - - faces = json.faces, - vertices = json.vertices, - normals = json.normals, - colors = json.colors, - - nUvLayers = 0; - - // disregard empty arrays - - for ( i = 0; i < json.uvs.length; i++ ) { - - if ( json.uvs[ i ].length ) nUvLayers ++; - - } - - for ( i = 0; i < nUvLayers; i++ ) { - - geometry.faceUvs[ i ] = []; - geometry.faceVertexUvs[ i ] = []; - - } - - offset = 0; - zLength = vertices.length; - - while ( offset < zLength ) { - - vertex = new THREE.Vertex(); - - vertex.position.x = vertices[ offset ++ ] * scale; - vertex.position.y = vertices[ offset ++ ] * scale; - vertex.position.z = vertices[ offset ++ ] * scale; - - geometry.vertices.push( vertex ); - - } - - offset = 0; - zLength = faces.length; - - while ( offset < zLength ) { - - type = faces[ offset ++ ]; - - - isQuad = isBitSet( type, 0 ); - hasMaterial = isBitSet( type, 1 ); - hasFaceUv = isBitSet( type, 2 ); - hasFaceVertexUv = isBitSet( type, 3 ); - hasFaceNormal = isBitSet( type, 4 ); - hasFaceVertexNormal = isBitSet( type, 5 ); - hasFaceColor = isBitSet( type, 6 ); - hasFaceVertexColor = isBitSet( type, 7 ); - - //console.log("type", type, "bits", isQuad, hasMaterial, hasFaceUv, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor); - - if ( isQuad ) { - - face = new THREE.Face4(); - - face.a = faces[ offset ++ ]; - face.b = faces[ offset ++ ]; - face.c = faces[ offset ++ ]; - face.d = faces[ offset ++ ]; - - nVertices = 4; - - } else { - - face = new THREE.Face3(); - - face.a = faces[ offset ++ ]; - face.b = faces[ offset ++ ]; - face.c = faces[ offset ++ ]; - - nVertices = 3; - - } - - if ( hasMaterial ) { - - materialIndex = faces[ offset ++ ]; - face.materials = geometry.materials[ materialIndex ]; - - } - - // to get face <=> uv index correspondence - - fi = geometry.faces.length; - - if ( hasFaceUv ) { - - for ( i = 0; i < nUvLayers; i++ ) { - - uvLayer = json.uvs[ i ]; - - uvIndex = faces[ offset ++ ]; - - u = uvLayer[ uvIndex * 2 ]; - v = uvLayer[ uvIndex * 2 + 1 ]; - - geometry.faceUvs[ i ][ fi ] = new THREE.UV( u, v ); - - } - - } - - if ( hasFaceVertexUv ) { - - for ( i = 0; i < nUvLayers; i++ ) { - - uvLayer = json.uvs[ i ]; - - uvs = []; - - for ( j = 0; j < nVertices; j ++ ) { - - uvIndex = faces[ offset ++ ]; - - u = uvLayer[ uvIndex * 2 ]; - v = uvLayer[ uvIndex * 2 + 1 ]; - - uvs[ j ] = new THREE.UV( u, v ); - - } - - geometry.faceVertexUvs[ i ][ fi ] = uvs; - - } - - } - - if ( hasFaceNormal ) { - - normalIndex = faces[ offset ++ ] * 3; - - normal = new THREE.Vector3(); - - normal.x = normals[ normalIndex ++ ]; - normal.y = normals[ normalIndex ++ ]; - normal.z = normals[ normalIndex ]; - - face.normal = normal; - - } - - if ( hasFaceVertexNormal ) { - - for ( i = 0; i < nVertices; i++ ) { - - normalIndex = faces[ offset ++ ] * 3; - - normal = new THREE.Vector3(); - - normal.x = normals[ normalIndex ++ ]; - normal.y = normals[ normalIndex ++ ]; - normal.z = normals[ normalIndex ]; - - face.vertexNormals.push( normal ); - - } - - } - - - if ( hasFaceColor ) { - - colorIndex = faces[ offset ++ ]; - - color = new THREE.Color( colors[ colorIndex ] ); - face.color = color; - - } - - - if ( hasFaceVertexColor ) { - - for ( i = 0; i < nVertices; i++ ) { - - colorIndex = faces[ offset ++ ]; - - color = new THREE.Color( colors[ colorIndex ] ); - face.vertexColors.push( color ); - - } - - } - - geometry.faces.push( face ); - - } - - }; - - function parseSkin() { - - var i, l, x, y, z, w, a, b, c, d; - - if ( json.skinWeights ) { - - for ( i = 0, l = json.skinWeights.length; i < l; i += 2 ) { - - x = json.skinWeights[ i ]; - y = json.skinWeights[ i + 1 ]; - z = 0; - w = 0; - - geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) ); - - } - - } - - if ( json.skinIndices ) { - - for ( i = 0, l = json.skinIndices.length; i < l; i += 2 ) { - - a = json.skinIndices[ i ]; - b = json.skinIndices[ i + 1 ]; - c = 0; - d = 0; - - geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) ); - - } - - } - - geometry.bones = json.bones; - geometry.animation = json.animation; - - }; - - function parseMorphing( scale ) { - - if ( json.morphTargets !== undefined ) { - - var i, l, v, vl, x, y, z, dstVertices, srcVertices; - - for ( i = 0, l = json.morphTargets.length; i < l; i++ ) { - - geometry.morphTargets[ i ] = {}; - geometry.morphTargets[ i ].name = json.morphTargets[ i ].name; - geometry.morphTargets[ i ].vertices = []; - - dstVertices = geometry.morphTargets[ i ].vertices; - srcVertices = json.morphTargets [ i ].vertices; - - for( v = 0, vl = srcVertices.length; v < vl; v += 3 ) { - - x = srcVertices[ v ] * scale; - y = srcVertices[ v + 1 ] * scale; - z = srcVertices[ v + 2 ] * scale; - - dstVertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) ); - - } - - } - - } - - if ( json.morphColors !== undefined ) { - - var i, l, c, cl, dstColors, srcColors, color; - - for ( i = 0, l = json.morphColors.length; i < l; i++ ) { - - geometry.morphColors[ i ] = {}; - geometry.morphColors[ i ].name = json.morphColors[ i ].name; - geometry.morphColors[ i ].colors = []; - - dstColors = geometry.morphColors[ i ].colors; - srcColors = json.morphColors [ i ].colors; - - for ( c = 0, cl = srcColors.length; c < cl; c += 3 ) { - - color = new THREE.Color( 0xffaa00 ); - color.setRGB( srcColors[ c ], srcColors[ c + 1 ], srcColors[ c + 2 ] ); - dstColors.push( color ); - - } - - } - - } - - }; - - function parseEdges() { - - if( json.edges !== undefined ) { - - var i, il, v1, v2; - - for ( i = 0; i < json.edges.length; i+= 2 ) { - - v1 = json.edges[ i ]; - v2 = json.edges[ i + 1 ]; - - geometry.edges.push( new THREE.Edge( geometry.vertices[ v1 ], geometry.vertices[ v2 ], v1, v2 ) ); - - } - - } - - }; - - callback( geometry ); - -} -/** - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.BinaryLoader = function ( showStatus ) { - - THREE.Loader.call( this, showStatus ); - -}; - -THREE.BinaryLoader.prototype = new THREE.Loader(); -THREE.BinaryLoader.prototype.constructor = THREE.BinaryLoader; -THREE.BinaryLoader.prototype.supr = THREE.Loader.prototype; - - -THREE.BinaryLoader.prototype = { - - // Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary) - // - binary models consist of two files: JS and BIN - // - parameters - // - model (required) - // - callback (required) - // - bin_path (optional: if not specified, binary file will be assumed to be in the same folder as JS model file) - // - texture_path (optional: if not specified, textures will be assumed to be in the same folder as JS model file) - - load: function( parameters ) { - - // #1 load JS part via web worker - - // This isn't really necessary, JS part is tiny, - // could be done by more ordinary means. - - var url = parameters.model, - callback = parameters.callback, - texture_path = parameters.texture_path ? parameters.texture_path : THREE.Loader.prototype.extractUrlbase( url ), - bin_path = parameters.bin_path ? parameters.bin_path : THREE.Loader.prototype.extractUrlbase( url ), - - s = (new Date).getTime(), - worker = new Worker( url ), - callback_progress = this.showProgress ? THREE.Loader.prototype.updateProgress : null; - - worker.onmessage = function( event ) { - - var materials = event.data.materials, - buffers = event.data.buffers; - - // #2 load BIN part via Ajax - - // For some reason it is faster doing loading from here than from within the worker. - // Maybe passing of ginormous string as message between threads is costly? - // Also, worker loading huge data by Ajax still freezes browser. Go figure, - // worker with baked ascii JSON data keeps browser more responsive. - - THREE.BinaryLoader.prototype.loadAjaxBuffers( buffers, materials, callback, bin_path, texture_path, callback_progress ); - - }; - - worker.onerror = function (event) { - - alert( "worker.onerror: " + event.message + "\n" + event.data ); - event.preventDefault(); - - }; - - worker.postMessage( s ); - - }, - - // Binary AJAX parser based on Magi binary loader - // https://github.com/kig/magi - - // Should look more into HTML5 File API - // See also other suggestions by Gregg Tavares - // https://groups.google.com/group/o3d-discuss/browse_thread/thread/a8967bc9ce1e0978 - - loadAjaxBuffers: function( buffers, materials, callback, bin_path, texture_path, callback_progress ) { - - var xhr = new XMLHttpRequest(), - url = bin_path + "/" + buffers; - - var length = 0; - - xhr.onreadystatechange = function() { - - if ( xhr.readyState == 4 ) { - - if ( xhr.status == 200 || xhr.status == 0 ) { - - THREE.BinaryLoader.prototype.createBinModel( xhr.responseText, callback, texture_path, materials ); - - } else { - - alert( "Couldn't load [" + url + "] [" + xhr.status + "]" ); - - } - - } else if ( xhr.readyState == 3 ) { - - if ( callback_progress ) { - - if ( length == 0 ) { - - length = xhr.getResponseHeader( "Content-Length" ); - - } - - callback_progress( { total: length, loaded: xhr.responseText.length } ); - - } - - } else if ( xhr.readyState == 2 ) { - - length = xhr.getResponseHeader( "Content-Length" ); - - } - - } - - xhr.open("GET", url, true); - xhr.overrideMimeType("text/plain; charset=x-user-defined"); - xhr.setRequestHeader("Content-Type", "text/plain"); - xhr.send(null); - - }, - - createBinModel: function ( data, callback, texture_path, materials ) { - - var Model = function ( texture_path ) { - - //var s = (new Date).getTime(); - - var scope = this, - currentOffset = 0, - md, - normals = [], - uvs = [], - tri_b, tri_c, tri_m, tri_na, tri_nb, tri_nc, - quad_b, quad_c, quad_d, quad_m, quad_na, quad_nb, quad_nc, quad_nd, - tri_uvb, tri_uvc, quad_uvb, quad_uvc, quad_uvd, - start_tri_flat, start_tri_smooth, start_tri_flat_uv, start_tri_smooth_uv, - start_quad_flat, start_quad_smooth, start_quad_flat_uv, start_quad_smooth_uv, - tri_size, quad_size, - len_tri_flat, len_tri_smooth, len_tri_flat_uv, len_tri_smooth_uv, - len_quad_flat, len_quad_smooth, len_quad_flat_uv, len_quad_smooth_uv; - - - THREE.Geometry.call( this ); - - THREE.Loader.prototype.init_materials( scope, materials, texture_path ); - - md = parseMetaData( data, currentOffset ); - currentOffset += md.header_bytes; - - // cache offsets - - tri_b = md.vertex_index_bytes, - tri_c = md.vertex_index_bytes*2, - tri_m = md.vertex_index_bytes*3, - tri_na = md.vertex_index_bytes*3 + md.material_index_bytes, - tri_nb = md.vertex_index_bytes*3 + md.material_index_bytes + md.normal_index_bytes, - tri_nc = md.vertex_index_bytes*3 + md.material_index_bytes + md.normal_index_bytes*2, - - quad_b = md.vertex_index_bytes, - quad_c = md.vertex_index_bytes*2, - quad_d = md.vertex_index_bytes*3, - quad_m = md.vertex_index_bytes*4, - quad_na = md.vertex_index_bytes*4 + md.material_index_bytes, - quad_nb = md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes, - quad_nc = md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes*2, - quad_nd = md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes*3, - - tri_uvb = md.uv_index_bytes, - tri_uvc = md.uv_index_bytes * 2, - - quad_uvb = md.uv_index_bytes, - quad_uvc = md.uv_index_bytes * 2, - quad_uvd = md.uv_index_bytes * 3; - - // buffers sizes - - tri_size = md.vertex_index_bytes * 3 + md.material_index_bytes; - quad_size = md.vertex_index_bytes * 4 + md.material_index_bytes; - - len_tri_flat = md.ntri_flat * ( tri_size ); - len_tri_smooth = md.ntri_smooth * ( tri_size + md.normal_index_bytes * 3 ); - len_tri_flat_uv = md.ntri_flat_uv * ( tri_size + md.uv_index_bytes * 3 ); - len_tri_smooth_uv = md.ntri_smooth_uv * ( tri_size + md.normal_index_bytes * 3 + md.uv_index_bytes * 3 ); - - len_quad_flat = md.nquad_flat * ( quad_size ); - len_quad_smooth = md.nquad_smooth * ( quad_size + md.normal_index_bytes * 4 ); - len_quad_flat_uv = md.nquad_flat_uv * ( quad_size + md.uv_index_bytes * 4 ); - len_quad_smooth_uv = md.nquad_smooth_uv * ( quad_size + md.normal_index_bytes * 4 + md.uv_index_bytes * 4 ); - - // read buffers - - currentOffset += init_vertices( currentOffset ); - currentOffset += init_normals( currentOffset ); - currentOffset += init_uvs( currentOffset ); - - start_tri_flat = currentOffset; - start_tri_smooth = start_tri_flat + len_tri_flat; - start_tri_flat_uv = start_tri_smooth + len_tri_smooth; - start_tri_smooth_uv = start_tri_flat_uv + len_tri_flat_uv; - - start_quad_flat = start_tri_smooth_uv + len_tri_smooth_uv; - start_quad_smooth = start_quad_flat + len_quad_flat; - start_quad_flat_uv = start_quad_smooth + len_quad_smooth; - start_quad_smooth_uv= start_quad_flat_uv +len_quad_flat_uv; - - // have to first process faces with uvs - // so that face and uv indices match - - init_triangles_flat_uv( start_tri_flat_uv ); - init_triangles_smooth_uv( start_tri_smooth_uv ); - - init_quads_flat_uv( start_quad_flat_uv ); - init_quads_smooth_uv( start_quad_smooth_uv ); - - // now we can process untextured faces - - init_triangles_flat( start_tri_flat ); - init_triangles_smooth( start_tri_smooth ); - - init_quads_flat( start_quad_flat ); - init_quads_smooth( start_quad_smooth ); - - this.computeCentroids(); - this.computeFaceNormals(); - - //var e = (new Date).getTime(); - - //log( "binary data parse time: " + (e-s) + " ms" ); - - function parseMetaData( data, offset ) { - - var metaData = { - - 'signature' :parseString( data, offset, 8 ), - 'header_bytes' :parseUChar8( data, offset + 8 ), - - 'vertex_coordinate_bytes' :parseUChar8( data, offset + 9 ), - 'normal_coordinate_bytes' :parseUChar8( data, offset + 10 ), - 'uv_coordinate_bytes' :parseUChar8( data, offset + 11 ), - - 'vertex_index_bytes' :parseUChar8( data, offset + 12 ), - 'normal_index_bytes' :parseUChar8( data, offset + 13 ), - 'uv_index_bytes' :parseUChar8( data, offset + 14 ), - 'material_index_bytes' :parseUChar8( data, offset + 15 ), - - 'nvertices' :parseUInt32( data, offset + 16 ), - 'nnormals' :parseUInt32( data, offset + 16 + 4*1 ), - 'nuvs' :parseUInt32( data, offset + 16 + 4*2 ), - - 'ntri_flat' :parseUInt32( data, offset + 16 + 4*3 ), - 'ntri_smooth' :parseUInt32( data, offset + 16 + 4*4 ), - 'ntri_flat_uv' :parseUInt32( data, offset + 16 + 4*5 ), - 'ntri_smooth_uv' :parseUInt32( data, offset + 16 + 4*6 ), - - 'nquad_flat' :parseUInt32( data, offset + 16 + 4*7 ), - 'nquad_smooth' :parseUInt32( data, offset + 16 + 4*8 ), - 'nquad_flat_uv' :parseUInt32( data, offset + 16 + 4*9 ), - 'nquad_smooth_uv' :parseUInt32( data, offset + 16 + 4*10 ) - - }; - - /* - log( "signature: " + metaData.signature ); - - log( "header_bytes: " + metaData.header_bytes ); - log( "vertex_coordinate_bytes: " + metaData.vertex_coordinate_bytes ); - log( "normal_coordinate_bytes: " + metaData.normal_coordinate_bytes ); - log( "uv_coordinate_bytes: " + metaData.uv_coordinate_bytes ); - - log( "vertex_index_bytes: " + metaData.vertex_index_bytes ); - log( "normal_index_bytes: " + metaData.normal_index_bytes ); - log( "uv_index_bytes: " + metaData.uv_index_bytes ); - log( "material_index_bytes: " + metaData.material_index_bytes ); - - log( "nvertices: " + metaData.nvertices ); - log( "nnormals: " + metaData.nnormals ); - log( "nuvs: " + metaData.nuvs ); - - log( "ntri_flat: " + metaData.ntri_flat ); - log( "ntri_smooth: " + metaData.ntri_smooth ); - log( "ntri_flat_uv: " + metaData.ntri_flat_uv ); - log( "ntri_smooth_uv: " + metaData.ntri_smooth_uv ); - - log( "nquad_flat: " + metaData.nquad_flat ); - log( "nquad_smooth: " + metaData.nquad_smooth ); - log( "nquad_flat_uv: " + metaData.nquad_flat_uv ); - log( "nquad_smooth_uv: " + metaData.nquad_smooth_uv ); - - var total = metaData.header_bytes - + metaData.nvertices * metaData.vertex_coordinate_bytes * 3 - + metaData.nnormals * metaData.normal_coordinate_bytes * 3 - + metaData.nuvs * metaData.uv_coordinate_bytes * 2 - + metaData.ntri_flat * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes ) - + metaData.ntri_smooth * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 ) - + metaData.ntri_flat_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.uv_index_bytes*3 ) - + metaData.ntri_smooth_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 + metaData.uv_index_bytes*3 ) - + metaData.nquad_flat * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes ) - + metaData.nquad_smooth * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 ) - + metaData.nquad_flat_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.uv_index_bytes*4 ) - + metaData.nquad_smooth_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 + metaData.uv_index_bytes*4 ); - log( "total bytes: " + total ); - */ - - return metaData; - - } - - function parseString( data, offset, length ) { - - return data.substr( offset, length ); - - } - - function parseFloat32( data, offset ) { - - var b3 = parseUChar8( data, offset ), - b2 = parseUChar8( data, offset + 1 ), - b1 = parseUChar8( data, offset + 2 ), - b0 = parseUChar8( data, offset + 3 ), - - sign = 1 - ( 2 * ( b0 >> 7 ) ), - exponent = ((( b0 << 1 ) & 0xff) | ( b1 >> 7 )) - 127, - mantissa = (( b1 & 0x7f ) << 16) | (b2 << 8) | b3; - - if (mantissa == 0 && exponent == -127) - return 0.0; - - return sign * ( 1 + mantissa * Math.pow( 2, -23 ) ) * Math.pow( 2, exponent ); - - } - - function parseUInt32( data, offset ) { - - var b0 = parseUChar8( data, offset ), - b1 = parseUChar8( data, offset + 1 ), - b2 = parseUChar8( data, offset + 2 ), - b3 = parseUChar8( data, offset + 3 ); - - return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0; - } - - function parseUInt16( data, offset ) { - - var b0 = parseUChar8( data, offset ), - b1 = parseUChar8( data, offset + 1 ); - - return (b1 << 8) + b0; - - } - - function parseSChar8( data, offset ) { - - var b = parseUChar8( data, offset ); - return b > 127 ? b - 256 : b; - - } - - function parseUChar8( data, offset ) { - - return data.charCodeAt( offset ) & 0xff; - } - - function init_vertices( start ) { - - var i, x, y, z, - stride = md.vertex_coordinate_bytes * 3, - end = start + md.nvertices * stride; - - for( i = start; i < end; i += stride ) { - - x = parseFloat32( data, i ); - y = parseFloat32( data, i + md.vertex_coordinate_bytes ); - z = parseFloat32( data, i + md.vertex_coordinate_bytes*2 ); - - THREE.BinaryLoader.prototype.v( scope, x, y, z ); - - } - - return md.nvertices * stride; - - } - - function init_normals( start ) { - - var i, x, y, z, - stride = md.normal_coordinate_bytes * 3, - end = start + md.nnormals * stride; - - for( i = start; i < end; i += stride ) { - - x = parseSChar8( data, i ); - y = parseSChar8( data, i + md.normal_coordinate_bytes ); - z = parseSChar8( data, i + md.normal_coordinate_bytes*2 ); - - normals.push( x/127, y/127, z/127 ); - - } - - return md.nnormals * stride; - - } - - function init_uvs( start ) { - - var i, u, v, - stride = md.uv_coordinate_bytes * 2, - end = start + md.nuvs * stride; - - for( i = start; i < end; i += stride ) { - - u = parseFloat32( data, i ); - v = parseFloat32( data, i + md.uv_coordinate_bytes ); - - uvs.push( u, v ); - - } - - return md.nuvs * stride; - - } - - function add_tri( i ) { - - var a, b, c, m; - - a = parseUInt32( data, i ); - b = parseUInt32( data, i + tri_b ); - c = parseUInt32( data, i + tri_c ); - - m = parseUInt16( data, i + tri_m ); - - THREE.BinaryLoader.prototype.f3( scope, a, b, c, m ); - - } - - function add_tri_n( i ) { - - var a, b, c, m, na, nb, nc; - - a = parseUInt32( data, i ); - b = parseUInt32( data, i + tri_b ); - c = parseUInt32( data, i + tri_c ); - - m = parseUInt16( data, i + tri_m ); - - na = parseUInt32( data, i + tri_na ); - nb = parseUInt32( data, i + tri_nb ); - nc = parseUInt32( data, i + tri_nc ); - - THREE.BinaryLoader.prototype.f3n( scope, normals, a, b, c, m, na, nb, nc ); - - } - - function add_quad( i ) { - - var a, b, c, d, m; - - a = parseUInt32( data, i ); - b = parseUInt32( data, i + quad_b ); - c = parseUInt32( data, i + quad_c ); - d = parseUInt32( data, i + quad_d ); - - m = parseUInt16( data, i + quad_m ); - - THREE.BinaryLoader.prototype.f4( scope, a, b, c, d, m ); - - } - - function add_quad_n( i ) { - - var a, b, c, d, m, na, nb, nc, nd; - - a = parseUInt32( data, i ); - b = parseUInt32( data, i + quad_b ); - c = parseUInt32( data, i + quad_c ); - d = parseUInt32( data, i + quad_d ); - - m = parseUInt16( data, i + quad_m ); - - na = parseUInt32( data, i + quad_na ); - nb = parseUInt32( data, i + quad_nb ); - nc = parseUInt32( data, i + quad_nc ); - nd = parseUInt32( data, i + quad_nd ); - - THREE.BinaryLoader.prototype.f4n( scope, normals, a, b, c, d, m, na, nb, nc, nd ); - - } - - function add_uv3( i ) { - - var uva, uvb, uvc, u1, u2, u3, v1, v2, v3; - - uva = parseUInt32( data, i ); - uvb = parseUInt32( data, i + tri_uvb ); - uvc = parseUInt32( data, i + tri_uvc ); - - u1 = uvs[ uva*2 ]; - v1 = uvs[ uva*2 + 1 ]; - - u2 = uvs[ uvb*2 ]; - v2 = uvs[ uvb*2 + 1 ]; - - u3 = uvs[ uvc*2 ]; - v3 = uvs[ uvc*2 + 1 ]; - - THREE.BinaryLoader.prototype.uv3( scope.faceVertexUvs[ 0 ], u1, v1, u2, v2, u3, v3 ); - - } - - function add_uv4( i ) { - - var uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4; - - uva = parseUInt32( data, i ); - uvb = parseUInt32( data, i + quad_uvb ); - uvc = parseUInt32( data, i + quad_uvc ); - uvd = parseUInt32( data, i + quad_uvd ); - - u1 = uvs[ uva*2 ]; - v1 = uvs[ uva*2 + 1 ]; - - u2 = uvs[ uvb*2 ]; - v2 = uvs[ uvb*2 + 1 ]; - - u3 = uvs[ uvc*2 ]; - v3 = uvs[ uvc*2 + 1 ]; - - u4 = uvs[ uvd*2 ]; - v4 = uvs[ uvd*2 + 1 ]; - - THREE.BinaryLoader.prototype.uv4( scope.faceVertexUvs[ 0 ], u1, v1, u2, v2, u3, v3, u4, v4 ); - - } - - function init_triangles_flat( start ) { - - var i, stride = md.vertex_index_bytes * 3 + md.material_index_bytes, - end = start + md.ntri_flat * stride; - - for( i = start; i < end; i += stride ) { - - add_tri( i ); - - } - - return end - start; - - } - - function init_triangles_flat_uv( start ) { - - var i, offset = md.vertex_index_bytes * 3 + md.material_index_bytes, - stride = offset + md.uv_index_bytes * 3, - end = start + md.ntri_flat_uv * stride; - - for( i = start; i < end; i += stride ) { - - add_tri( i ); - add_uv3( i + offset ); - - } - - return end - start; - - } - - function init_triangles_smooth( start ) { - - var i, stride = md.vertex_index_bytes * 3 + md.material_index_bytes + md.normal_index_bytes * 3, - end = start + md.ntri_smooth * stride; - - for( i = start; i < end; i += stride ) { - - add_tri_n( i ); - - } - - return end - start; - - } - - function init_triangles_smooth_uv( start ) { - - var i, offset = md.vertex_index_bytes * 3 + md.material_index_bytes + md.normal_index_bytes * 3, - stride = offset + md.uv_index_bytes * 3, - end = start + md.ntri_smooth_uv * stride; - - for( i = start; i < end; i += stride ) { - - add_tri_n( i ); - add_uv3( i + offset ); - - } - - return end - start; - - } - - function init_quads_flat( start ) { - - var i, stride = md.vertex_index_bytes * 4 + md.material_index_bytes, - end = start + md.nquad_flat * stride; - - for( i = start; i < end; i += stride ) { - - add_quad( i ); - - } - - return end - start; - - } - - function init_quads_flat_uv( start ) { - - var i, offset = md.vertex_index_bytes * 4 + md.material_index_bytes, - stride = offset + md.uv_index_bytes * 4, - end = start + md.nquad_flat_uv * stride; - - for( i = start; i < end; i += stride ) { - - add_quad( i ); - add_uv4( i + offset ); - - } - - return end - start; - - } - - function init_quads_smooth( start ) { - - var i, stride = md.vertex_index_bytes * 4 + md.material_index_bytes + md.normal_index_bytes * 4, - end = start + md.nquad_smooth * stride; - - for( i = start; i < end; i += stride ) { - - add_quad_n( i ); - } - - return end - start; - - } - - function init_quads_smooth_uv( start ) { - - var i, offset = md.vertex_index_bytes * 4 + md.material_index_bytes + md.normal_index_bytes * 4, - stride = offset + md.uv_index_bytes * 4, - end = start + md.nquad_smooth_uv * stride; - - for( i = start; i < end; i += stride ) { - - add_quad_n( i ); - add_uv4( i + offset ); - - } - - return end - start; - - } - - } - - Model.prototype = new THREE.Geometry(); - Model.prototype.constructor = Model; - - callback( new Model( texture_path ) ); - - }, - - - v: function( scope, x, y, z ) { - - scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) ); - - }, - - f3: function( scope, a, b, c, mi ) { - - var material = scope.materials[ mi ]; - scope.faces.push( new THREE.Face3( a, b, c, null, null, material ) ); - - }, - - f4: function( scope, a, b, c, d, mi ) { - - var material = scope.materials[ mi ]; - scope.faces.push( new THREE.Face4( a, b, c, d, null, null, material ) ); - - }, - - f3n: function( scope, normals, a, b, c, mi, na, nb, nc ) { - - var material = scope.materials[ mi ], - nax = normals[ na*3 ], - nay = normals[ na*3 + 1 ], - naz = normals[ na*3 + 2 ], - - nbx = normals[ nb*3 ], - nby = normals[ nb*3 + 1 ], - nbz = normals[ nb*3 + 2 ], - - ncx = normals[ nc*3 ], - ncy = normals[ nc*3 + 1 ], - ncz = normals[ nc*3 + 2 ]; - - scope.faces.push( new THREE.Face3( a, b, c, - [new THREE.Vector3( nax, nay, naz ), - new THREE.Vector3( nbx, nby, nbz ), - new THREE.Vector3( ncx, ncy, ncz )], - null, - material ) ); - - }, - - f4n: function( scope, normals, a, b, c, d, mi, na, nb, nc, nd ) { - - var material = scope.materials[ mi ], - nax = normals[ na*3 ], - nay = normals[ na*3 + 1 ], - naz = normals[ na*3 + 2 ], - - nbx = normals[ nb*3 ], - nby = normals[ nb*3 + 1 ], - nbz = normals[ nb*3 + 2 ], - - ncx = normals[ nc*3 ], - ncy = normals[ nc*3 + 1 ], - ncz = normals[ nc*3 + 2 ], - - ndx = normals[ nd*3 ], - ndy = normals[ nd*3 + 1 ], - ndz = normals[ nd*3 + 2 ]; - - scope.faces.push( new THREE.Face4( a, b, c, d, - [new THREE.Vector3( nax, nay, naz ), - new THREE.Vector3( nbx, nby, nbz ), - new THREE.Vector3( ncx, ncy, ncz ), - new THREE.Vector3( ndx, ndy, ndz )], - null, - material ) ); - - }, - - uv3: function( where, u1, v1, u2, v2, u3, v3 ) { - - var uv = []; - uv.push( new THREE.UV( u1, v1 ) ); - uv.push( new THREE.UV( u2, v2 ) ); - uv.push( new THREE.UV( u3, v3 ) ); - where.push( uv ); - - }, - - uv4: function( where, u1, v1, u2, v2, u3, v3, u4, v4 ) { - - var uv = []; - uv.push( new THREE.UV( u1, v1 ) ); - uv.push( new THREE.UV( u2, v2 ) ); - uv.push( new THREE.UV( u3, v3 ) ); - uv.push( new THREE.UV( u4, v4 ) ); - where.push( uv ); - - } - -}; -/** - * @author alteredq / http://alteredqualia.com/ - */ - -THREE.SceneLoader = function () { - - this.onLoadStart = function () {}; - this.onLoadProgress = function() {}; - this.onLoadComplete = function () {}; - - this.callbackSync = function () {}; - this.callbackProgress = function () {}; - -}; - -THREE.SceneLoader.prototype = { - - load : function ( url, callbackFinished ) { - - var scope = this; - - var worker = new Worker( url ); - worker.postMessage( 0 ); - - var urlBase = THREE.Loader.prototype.extractUrlbase( url ); - - worker.onmessage = function( event ) { - - var dg, dm, dd, dl, dc, df, dt, - g, o, m, l, p, c, t, f, tt, pp, - geometry, material, camera, fog, - texture, images, - materials, - data, binLoader, jsonLoader, - counter_models, counter_textures, - total_models, total_textures, - result; - - data = event.data; - - binLoader = new THREE.BinaryLoader(); - jsonLoader = new THREE.JSONLoader(); - - counter_models = 0; - counter_textures = 0; - - result = { - - scene: new THREE.Scene(), - geometries: {}, - materials: {}, - textures: {}, - objects: {}, - cameras: {}, - lights: {}, - fogs: {}, - triggers: {}, - empties: {} - - }; - - // find out if there are some colliders - - var hasColliders = false; - - for( dd in data.objects ) { - - o = data.objects[ dd ]; - - if ( o.meshCollider ) { - - hasColliders = true; - break; - - } - - } - - if ( hasColliders ) { - - result.scene.collisions = new THREE.CollisionSystem(); - - } - - if ( data.transform ) { - - var position = data.transform.position, - rotation = data.transform.rotation, - scale = data.transform.scale; - - if ( position ) - result.scene.position.set( position[ 0 ], position[ 1 ], position [ 2 ] ); - - if ( rotation ) - result.scene.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation [ 2 ] ); - - if ( scale ) - result.scene.scale.set( scale[ 0 ], scale[ 1 ], scale [ 2 ] ); - - if ( position || rotation || scale ) - result.scene.updateMatrix(); - - } - - function get_url( source_url, url_type ) { - - if ( url_type == "relativeToHTML" ) { - - return source_url; - - } else { - - return urlBase + "/" + source_url; - - } - - }; - - function handle_objects() { - - for( dd in data.objects ) { - - if ( !result.objects[ dd ] ) { - - o = data.objects[ dd ]; - - if ( o.geometry !== undefined ) { - - geometry = result.geometries[ o.geometry ]; - - // geometry already loaded - - if ( geometry ) { - - materials = []; - for( i = 0; i < o.materials.length; i++ ) { - - materials[ i ] = result.materials[ o.materials[i] ]; - - } - - p = o.position; - r = o.rotation; - q = o.quaternion; - s = o.scale; - - // turn off quaternions, for the moment - - q = 0; - - if ( materials.length == 0 ) { - - materials[ 0 ] = new THREE.MeshFaceMaterial(); - - } - - // dirty hack to handle meshes with multiple materials - // just use face materials defined in model - - if ( materials.length > 1 ) { - - materials = [ new THREE.MeshFaceMaterial() ]; - - } - - object = new THREE.Mesh( geometry, materials ); - object.name = dd; - object.position.set( p[0], p[1], p[2] ); - - if ( q ) { - - object.quaternion.set( q[0], q[1], q[2], q[3] ); - object.useQuaternion = true; - - } else { - - object.rotation.set( r[0], r[1], r[2] ); - - } - - object.scale.set( s[0], s[1], s[2] ); - object.visible = o.visible; - - result.scene.addObject( object ); - - result.objects[ dd ] = object; - - if ( o.meshCollider ) { - - var meshCollider = THREE.CollisionUtils.MeshColliderWBox( object ); - result.scene.collisions.colliders.push( meshCollider ); - - } - - if ( o.castsShadow ) { - - //object.visible = true; - //object.materials = [ new THREE.MeshBasicMaterial( { color: 0xff0000 } ) ]; - - var shadow = new THREE.ShadowVolume( geometry ) - result.scene.addChild( shadow ); - - shadow.position = object.position; - shadow.rotation = object.rotation; - shadow.scale = object.scale; - - } - - if ( o.trigger && o.trigger.toLowerCase() != "none" ) { - - var trigger = { - "type" : o.trigger, - "object" : o - }; - - result.triggers[ object.name ] = trigger; - - } - - } - - // pure Object3D - - } else { - - p = o.position; - r = o.rotation; - q = o.quaternion; - s = o.scale; - - // turn off quaternions, for the moment - - q = 0; - - object = new THREE.Object3D(); - object.name = dd; - object.position.set( p[0], p[1], p[2] ); - - if ( q ) { - - object.quaternion.set( q[0], q[1], q[2], q[3] ); - object.useQuaternion = true; - - } else { - - object.rotation.set( r[0], r[1], r[2] ); - - } - - object.scale.set( s[0], s[1], s[2] ); - object.visible = ( o.visible !== undefined ) ? o.visible : false; - - result.scene.addObject( object ); - - result.objects[ dd ] = object; - result.empties[ dd ] = object; - - - if ( o.trigger && o.trigger.toLowerCase() != "none" ) { - - var trigger = { - "type" : o.trigger, - "object" : o - }; - - result.triggers[ object.name ] = trigger; - - } - - } - - } - - } - - }; - - function handle_mesh( geo, id ) { - - result.geometries[ id ] = geo; - handle_objects(); - - }; - - function create_callback( id ) { - - return function( geo ) { - - handle_mesh( geo, id ); - - counter_models -= 1; - - scope.onLoadComplete(); - - async_callback_gate(); - - } - - }; - - function create_callback_embed( id ) { - - return function( geo ) { - - result.geometries[ id ] = geo; - - } - - }; - - function async_callback_gate() { - - var progress = { - - totalModels : total_models, - totalTextures : total_textures, - loadedModels : total_models - counter_models, - loadedTextures : total_textures - counter_textures - - }; - - scope.callbackProgress( progress, result ); - - scope.onLoadProgress(); - - if( counter_models == 0 && counter_textures == 0 ) { - - callbackFinished( result ); - - } - - }; - - var callbackTexture = function( images ) { - - counter_textures -= 1; - async_callback_gate(); - - scope.onLoadComplete(); - - }; - - // first go synchronous elements - - // cameras - - for( dc in data.cameras ) { - - c = data.cameras[ dc ]; - - if ( c.type == "perspective" ) { - - camera = new THREE.Camera( c.fov, c.aspect, c.near, c.far ); - - } else if ( c.type == "ortho" ) { - - camera = new THREE.Camera(); - camera.projectionMatrix = THREE.Matrix4.makeOrtho( c.left, c.right, c.top, c.bottom, c.near, c.far ); - - } - - p = c.position; - t = c.target; - camera.position.set( p[0], p[1], p[2] ); - camera.target.position.set( t[0], t[1], t[2] ); - - result.cameras[ dc ] = camera; - - } - - // lights - - var hex, intensity; - - for ( dl in data.lights ) { - - l = data.lights[ dl ]; - - hex = ( l.color !== undefined ) ? l.color : 0xffffff; - intensity = ( l.intensity !== undefined ) ? l.intensity : 1; - - if ( l.type == "directional" ) { - - p = l.direction; - - light = new THREE.DirectionalLight( hex, intensity ); - light.position.set( p[0], p[1], p[2] ); - light.position.normalize(); - - } else if ( l.type == "point" ) { - - p = l.position; - - light = new THREE.PointLight( hex, intensity ); - light.position.set( p[0], p[1], p[2] ); - - } - - result.scene.addLight( light ); - - result.lights[ dl ] = light; - - } - - // fogs - - for( df in data.fogs ) { - - f = data.fogs[ df ]; - - if ( f.type == "linear" ) { - - fog = new THREE.Fog( 0x000000, f.near, f.far ); - - } else if ( f.type == "exp2" ) { - - fog = new THREE.FogExp2( 0x000000, f.density ); - - } - - c = f.color; - fog.color.setRGB( c[0], c[1], c[2] ); - - result.fogs[ df ] = fog; - - } - - // defaults - - if ( result.cameras && data.defaults.camera ) { - - result.currentCamera = result.cameras[ data.defaults.camera ]; - - } - - if ( result.fogs && data.defaults.fog ) { - - result.scene.fog = result.fogs[ data.defaults.fog ]; - - } - - c = data.defaults.bgcolor; - result.bgColor = new THREE.Color(); - result.bgColor.setRGB( c[0], c[1], c[2] ); - - result.bgColorAlpha = data.defaults.bgalpha; - - // now come potentially asynchronous elements - - // geometries - - // count how many models will be loaded asynchronously - - for( dg in data.geometries ) { - - g = data.geometries[ dg ]; - - if ( g.type == "bin_mesh" || g.type == "ascii_mesh" ) { - - counter_models += 1; - - scope.onLoadStart(); - - } - - } - - total_models = counter_models; - - for ( dg in data.geometries ) { - - g = data.geometries[ dg ]; - - if ( g.type == "cube" ) { - - geometry = new THREE.CubeGeometry( g.width, g.height, g.depth, g.segmentsWidth, g.segmentsHeight, g.segmentsDepth, null, g.flipped, g.sides ); - result.geometries[ dg ] = geometry; - - } else if ( g.type == "plane" ) { - - geometry = new THREE.PlaneGeometry( g.width, g.height, g.segmentsWidth, g.segmentsHeight ); - result.geometries[ dg ] = geometry; - - } else if ( g.type == "sphere" ) { - - geometry = new THREE.SphereGeometry( g.radius, g.segmentsWidth, g.segmentsHeight ); - result.geometries[ dg ] = geometry; - - } else if ( g.type == "cylinder" ) { - - geometry = new THREE.CylinderGeometry( g.numSegs, g.topRad, g.botRad, g.height, g.topOffset, g.botOffset ); - result.geometries[ dg ] = geometry; - - } else if ( g.type == "torus" ) { - - geometry = new THREE.TorusGeometry( g.radius, g.tube, g.segmentsR, g.segmentsT ); - result.geometries[ dg ] = geometry; - - } else if ( g.type == "icosahedron" ) { - - geometry = new THREE.IcosahedronGeometry( g.subdivisions ); - result.geometries[ dg ] = geometry; - - } else if ( g.type == "bin_mesh" ) { - - binLoader.load( { model: get_url( g.url, data.urlBaseType ), - callback: create_callback( dg ) - } ); - - } else if ( g.type == "ascii_mesh" ) { - - jsonLoader.load( { model: get_url( g.url, data.urlBaseType ), - callback: create_callback( dg ) - } ); - - } else if ( g.type == "embedded_mesh" ) { - - var modelJson = data.embeds[ g.id ], - texture_path = ""; - - if ( modelJson ) { - - jsonLoader.createModel( modelJson, create_callback_embed( dg ), texture_path ); - - } - - } - - } - - // textures - - // count how many textures will be loaded asynchronously - - for( dt in data.textures ) { - - tt = data.textures[ dt ]; - - if( tt.url instanceof Array ) { - - counter_textures += tt.url.length; - - for( var n = 0; n < tt.url.length; n ++ ) { - - scope.onLoadStart(); - - } - - } else { - - counter_textures += 1; - - scope.onLoadStart(); - - } - - } - - total_textures = counter_textures; - - for( dt in data.textures ) { - - tt = data.textures[ dt ]; - - if ( tt.mapping != undefined && THREE[ tt.mapping ] != undefined ) { - - tt.mapping = new THREE[ tt.mapping ](); - - } - - if( tt.url instanceof Array ) { - - var url_array = []; - - for( var i = 0; i < tt.url.length; i ++ ) { - - url_array[ i ] = get_url( tt.url[ i ], data.urlBaseType ); - - } - - texture = THREE.ImageUtils.loadTextureCube( url_array, tt.mapping, callbackTexture ); - - } else { - - texture = THREE.ImageUtils.loadTexture( get_url( tt.url, data.urlBaseType ), tt.mapping, callbackTexture ); - - if ( THREE[ tt.minFilter ] != undefined ) - texture.minFilter = THREE[ tt.minFilter ]; - - if ( THREE[ tt.magFilter ] != undefined ) - texture.magFilter = THREE[ tt.magFilter ]; - - if ( tt.repeat ) { - - texture.repeat.set( tt.repeat[ 0 ], tt.repeat[ 1 ] ); - texture.wrapS = texture.wrapT = THREE.RepeatWrapping; - - } - - } - - result.textures[ dt ] = texture; - - } - - // materials - - for ( dm in data.materials ) { - - m = data.materials[ dm ]; - - for ( pp in m.parameters ) { - - if ( pp == "envMap" || pp == "map" || pp == "lightMap" ) { - - m.parameters[ pp ] = result.textures[ m.parameters[ pp ] ]; - - } else if ( pp == "shading" ) { - - m.parameters[ pp ] = ( m.parameters[ pp ] == "flat" ) ? THREE.FlatShading : THREE.SmoothShading; - - } else if ( pp == "blending" ) { - - m.parameters[ pp ] = THREE[ m.parameters[ pp ] ] ? THREE[ m.parameters[ pp ] ] : THREE.NormalBlending; - - } else if ( pp == "combine" ) { - - m.parameters[ pp ] = ( m.parameters[ pp ] == "MixOperation" ) ? THREE.MixOperation : THREE.MultiplyOperation; - - } else if ( pp == "vertexColors" ) { - - if ( m.parameters[ pp ] == "face" ) { - - m.parameters[ pp ] = THREE.FaceColors; - - // default to vertex colors if "vertexColors" is anything else face colors or 0 / null / false - - } else if ( m.parameters[ pp ] ) { - - m.parameters[ pp ] = THREE.VertexColors; - - } - - } - - } - - if ( m.parameters.opacity !== undefined && m.parameters.opacity < 1.0 ) { - - m.parameters.transparent = true; - - } - - material = new THREE[ m.type ]( m.parameters ); - result.materials[ dm ] = material; - - } - - // objects ( synchronous init of procedural primitives ) - - handle_objects(); - - // synchronous callback - - scope.callbackSync( result ); - - }; - - } - -}; -/** - * @author alteredq / http://alteredqualia.com/ - * - * Port of greggman's ThreeD version of marching cubes to Three.js - * http://webglsamples.googlecode.com/hg/blob/blob.html - */ - -// do not crash if somebody includes the file in oldie browser - -THREE.MarchingCubes = function ( resolution, materials ) { - - THREE.Object3D.call( this ); - - this.materials = materials instanceof Array ? materials : [ materials ]; - - // functions have to be object properties - // prototype functions kill performance - // (tested and it was 4x slower !!!) - - this.init = function( resolution ) { - - // parameters - - this.isolation = 80.0; - - // size of field, 32 is pushing it in Javascript :) - - this.size = resolution; - this.size2 = this.size * this.size; - this.size3 = this.size2 * this.size; - this.halfsize = this.size / 2.0; - - // deltas - - this.delta = 2.0 / this.size; - this.yd = this.size; - this.zd = this.size2; - - this.field = new Float32Array( this.size3 ); - this.normal_cache = new Float32Array( this.size3 * 3 ); - - // temp buffers used in polygonize - - this.vlist = new Float32Array( 12 * 3 ); - this.nlist = new Float32Array( 12 * 3 ); - - this.firstDraw = true; - - // immediate render mode simulator - - this.maxCount = 4096; // TODO: find the fastest size for this buffer - this.count = 0; - this.hasPos = false; - this.hasNormal = false; - - this.positionArray = new Float32Array( this.maxCount * 3 ); - this.normalArray = new Float32Array( this.maxCount * 3 ); - - }; - - /////////////////////// - // Polygonization - /////////////////////// - - this.lerp = function( a, b, t ) { return a + ( b - a ) * t; }; - - this.VIntX = function( q, pout, nout, offset, isol, x, y, z, valp1, valp2 ) { - - var mu = ( isol - valp1 ) / ( valp2 - valp1 ), - nc = this.normal_cache; - - pout[ offset ] = x + mu * this.delta; - pout[ offset + 1 ] = y; - pout[ offset + 2 ] = z; - - nout[ offset ] = this.lerp( nc[ q ], nc[ q + 3 ], mu ); - nout[ offset + 1 ] = this.lerp( nc[ q + 1 ], nc[ q + 4 ], mu ); - nout[ offset + 2 ] = this.lerp( nc[ q + 2 ], nc[ q + 5 ], mu ); - - }; - - this.VIntY = function( q, pout, nout, offset, isol, x, y, z, valp1, valp2 ) { - - var mu = ( isol - valp1 ) / ( valp2 - valp1 ), - nc = this.normal_cache; - - pout[ offset ] = x; - pout[ offset + 1 ] = y + mu * this.delta; - pout[ offset + 2 ] = z; - - var q2 = q + this.yd * 3; - - nout[ offset ] = this.lerp( nc[ q ], nc[ q2 ], mu ); - nout[ offset + 1 ] = this.lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu ); - nout[ offset + 2 ] = this.lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu ); - - }; - - this.VIntZ = function( q, pout, nout, offset, isol, x, y, z, valp1, valp2 ) { - - var mu = ( isol - valp1 ) / ( valp2 - valp1 ), - nc = this.normal_cache; - - pout[ offset ] = x; - pout[ offset + 1 ] = y; - pout[ offset + 2 ] = z + mu * this.delta; - - var q2 = q + this.zd * 3; - - nout[ offset ] = this.lerp( nc[ q ], nc[ q2 ], mu ); - nout[ offset + 1 ] = this.lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu ); - nout[ offset + 2 ] = this.lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu ); - - }; - - this.compNorm = function( q ) { - - var q3 = q * 3; - - if ( this.normal_cache [ q3 ] == 0.0 ) { - - this.normal_cache[ q3 ] = this.field[ q - 1 ] - this.field[ q + 1 ]; - this.normal_cache[ q3 + 1 ] = this.field[ q - this.yd ] - this.field[ q + this.yd ]; - this.normal_cache[ q3 + 2 ] = this.field[ q - this.zd ] - this.field[ q + this.zd ]; - - } - - }; - - // Returns total number of triangles. Fills triangles. - // (this is where most of time is spent - it's inner work of O(n3) loop ) - - this.polygonize = function( fx, fy, fz, q, isol, render_callback ) { - - // cache indices - var q1 = q + 1, - qy = q + this.yd, - qz = q + this.zd, - q1y = q1 + this.yd, - q1z = q1 + this.zd, - qyz = q + this.yd + this.zd, - q1yz = q1 + this.yd + this.zd; - - var cubeindex = 0, - field0 = this.field[ q ], - field1 = this.field[ q1 ], - field2 = this.field[ qy ], - field3 = this.field[ q1y ], - field4 = this.field[ qz ], - field5 = this.field[ q1z ], - field6 = this.field[ qyz ], - field7 = this.field[ q1yz ]; - - if ( field0 < isol ) cubeindex |= 1; - if ( field1 < isol ) cubeindex |= 2; - if ( field2 < isol ) cubeindex |= 8; - if ( field3 < isol ) cubeindex |= 4; - if ( field4 < isol ) cubeindex |= 16; - if ( field5 < isol ) cubeindex |= 32; - if ( field6 < isol ) cubeindex |= 128; - if ( field7 < isol ) cubeindex |= 64; - - // if cube is entirely in/out of the surface - bail, nothing to draw - - var bits = THREE.edgeTable[ cubeindex ]; - if ( bits == 0 ) return 0; - - var d = this.delta, - fx2 = fx + d, - fy2 = fy + d, - fz2 = fz + d; - - // top of the cube - - if ( bits & 1 ) { - - this.compNorm( q ); - this.compNorm( q1 ); - this.VIntX( q * 3, this.vlist, this.nlist, 0, isol, fx, fy, fz, field0, field1 ); - - }; - - if ( bits & 2 ) { - - this.compNorm( q1 ); - this.compNorm( q1y ); - this.VIntY( q1 * 3, this.vlist, this.nlist, 3, isol, fx2, fy, fz, field1, field3 ); - - }; - - if ( bits & 4 ) { - - this.compNorm( qy ); - this.compNorm( q1y ); - this.VIntX( qy * 3, this.vlist, this.nlist, 6, isol, fx, fy2, fz, field2, field3 ); - - }; - - if ( bits & 8 ) { - - this.compNorm( q ); - this.compNorm( qy ); - this.VIntY( q * 3, this.vlist, this.nlist, 9, isol, fx, fy, fz, field0, field2 ); - - }; - - // bottom of the cube - - if ( bits & 16 ) { - - this.compNorm( qz ); - this.compNorm( q1z ); - this.VIntX( qz * 3, this.vlist, this.nlist, 12, isol, fx, fy, fz2, field4, field5 ); - - }; - - if ( bits & 32 ) { - - this.compNorm( q1z ); - this.compNorm( q1yz ); - this.VIntY( q1z * 3, this.vlist, this.nlist, 15, isol, fx2, fy, fz2, field5, field7 ); - - }; - - if ( bits & 64 ) { - - this.compNorm( qyz ); - this.compNorm( q1yz ); - this.VIntX( qyz * 3, this.vlist, this.nlist, 18, isol, fx, fy2, fz2, field6, field7 ); - - }; - - if ( bits & 128 ) { - - this.compNorm( qz ); - this.compNorm( qyz ); - this.VIntY( qz * 3, this.vlist, this.nlist, 21, isol, fx, fy, fz2, field4, field6 ); - - }; - - // vertical lines of the cube - - if ( bits & 256 ) { - - this.compNorm( q ); - this.compNorm( qz ); - this.VIntZ( q * 3, this.vlist, this.nlist, 24, isol, fx, fy, fz, field0, field4 ); - - }; - - if ( bits & 512 ) { - - this.compNorm( q1 ); - this.compNorm( q1z ); - this.VIntZ( q1 * 3, this.vlist, this.nlist, 27, isol, fx2, fy, fz, field1, field5 ); - - }; - - if ( bits & 1024 ) { - - this.compNorm( q1y ); - this.compNorm( q1yz ); - this.VIntZ( q1y * 3, this.vlist, this.nlist, 30, isol, fx2, fy2, fz, field3, field7 ); - - }; - - if ( bits & 2048 ) { - - this.compNorm( qy ); - this.compNorm( qyz ); - this.VIntZ( qy * 3, this.vlist, this.nlist, 33, isol, fx, fy2, fz, field2, field6 ); - - }; - - cubeindex <<= 4; // re-purpose cubeindex into an offset into triTable - - var o1, o2, o3, numtris = 0, i = 0; - - // here is where triangles are created - - while ( THREE.triTable[ cubeindex + i ] != -1 ) { - - o1 = cubeindex + i; - o2 = o1 + 1; - o3 = o1 + 2; - - this.posnormtriv( this.vlist, this.nlist, - 3 * THREE.triTable[ o1 ], - 3 * THREE.triTable[ o2 ], - 3 * THREE.triTable[ o3 ], - render_callback ); - - i += 3; - numtris ++; - - } - - return numtris; - - }; - - ///////////////////////////////////// - // Immediate render mode simulator - ///////////////////////////////////// - - this.posnormtriv = function( pos, norm, o1, o2, o3, render_callback ) { - - var c = this.count * 3; - - this.positionArray[ c ] = pos[ o1 ]; - this.positionArray[ c + 1 ] = pos[ o1 + 1 ]; - this.positionArray[ c + 2 ] = pos[ o1 + 2 ]; - - this.positionArray[ c + 3 ] = pos[ o2 ]; - this.positionArray[ c + 4 ] = pos[ o2 + 1 ]; - this.positionArray[ c + 5 ] = pos[ o2 + 2 ]; - - this.positionArray[ c + 6 ] = pos[ o3 ]; - this.positionArray[ c + 7 ] = pos[ o3 + 1 ]; - this.positionArray[ c + 8 ] = pos[ o3 + 2 ]; - - this.normalArray[ c ] = norm[ o1 ]; - this.normalArray[ c + 1 ] = norm[ o1 + 1 ]; - this.normalArray[ c + 2 ] = norm[ o1 + 2 ]; - - this.normalArray[ c + 3 ] = norm[ o2 ]; - this.normalArray[ c + 4 ] = norm[ o2 + 1 ]; - this.normalArray[ c + 5 ] = norm[ o2 + 2 ]; - - this.normalArray[ c + 6 ] = norm[ o3 ]; - this.normalArray[ c + 7 ] = norm[ o3 + 1 ]; - this.normalArray[ c + 8 ] = norm[ o3 + 2 ]; - - this.hasPos = true; - this.hasNormal = true; - - this.count += 3; - - if ( this.count >= this.maxCount - 3 ) { - - render_callback( this ); - - } - - }; - - this.begin = function( ) { - - this.count = 0; - this.hasPos = false; - this.hasNormal = false; - - }; - - this.end = function( render_callback ) { - - if ( this.count == 0 ) - return; - - for ( var i = this.count * 3; i < this.positionArray.length; i++ ) - this.positionArray[ i ] = 0.0; - - render_callback( this ); - - }; - - ///////////////////////////////////// - // Metaballs - ///////////////////////////////////// - - // Adds a reciprocal ball (nice and blobby) that, to be fast, fades to zero after - // a fixed distance, determined by strength and subtract. - - this.addBall = function( ballx, bally, ballz, strength, subtract ) { - - // Let's solve the equation to find the radius: - // 1.0 / (0.000001 + radius^2) * strength - subtract = 0 - // strength / (radius^2) = subtract - // strength = subtract * radius^2 - // radius^2 = strength / subtract - // radius = sqrt(strength / subtract) - - var radius = this.size * Math.sqrt( strength / subtract ), - zs = ballz * this.size, - ys = bally * this.size, - xs = ballx * this.size; - - var min_z = Math.floor( zs - radius ); if ( min_z < 1 ) min_z = 1; - var max_z = Math.floor( zs + radius ); if ( max_z > this.size - 1 ) max_z = this.size - 1; - var min_y = Math.floor( ys - radius ); if ( min_y < 1 ) min_y = 1; - var max_y = Math.floor( ys + radius ); if ( max_y > this.size - 1 ) max_y = this.size - 1; - var min_x = Math.floor( xs - radius ); if ( min_x < 1 ) min_x = 1; - var max_x = Math.floor( xs + radius ); if ( max_x > this.size - 1 ) max_x = this.size - 1; - - - // Don't polygonize in the outer layer because normals aren't - // well-defined there. - - var x, y, z, y_offset, z_offset, fx, fy, fz, fz2, fy2, val; - - for ( z = min_z; z < max_z; z++ ) { - - z_offset = this.size2 * z, - fz = z / this.size - ballz, - fz2 = fz * fz; - - for ( y = min_y; y < max_y; y++ ) { - - y_offset = z_offset + this.size * y; - fy = y / this.size - bally; - fy2 = fy * fy; - - for ( x = min_x; x < max_x; x++ ) { - - fx = x / this.size - ballx; - val = strength / ( 0.000001 + fx*fx + fy2 + fz2 ) - subtract; - if ( val > 0.0 ) this.field[ y_offset + x ] += val; - - } - - } - - } - - }; - - this.addPlaneX = function( strength, subtract ) { - - var x, y, z, xx, val, xdiv, cxy, - - // cache attribute lookups - size = this.size, - yd = this.yd, - zd = this.zd, - field = this.field, - - dist = size * Math.sqrt( strength / subtract ); - - if ( dist > size ) dist = size; - - for ( x = 0; x < dist; x++ ) { - - xdiv = x / size; - xx = xdiv * xdiv; - val = strength / ( 0.0001 + xx ) - subtract; - - if ( val > 0.0 ) { - - for ( y = 0; y < size; y++ ) { - - cxy = x + y * yd; - - for ( z = 0; z < size; z++ ) { - - field[ zd * z + cxy ] += val; - - } - - } - - } - - } - - }; - - this.addPlaneY = function( strength, subtract ) { - - var x, y, z, yy, val, ydiv, cy, cxy, - - // cache attribute lookups - size = this.size, - yd = this.yd, - zd = this.zd, - field = this.field, - - dist = size * Math.sqrt( strength / subtract ); - - if ( dist > size ) dist = size; - - for ( y = 0; y < dist; y++ ) { - - ydiv = y / size; - yy = ydiv * ydiv; - val = strength / ( 0.0001 + yy ) - subtract; - - if ( val > 0.0 ) { - - cy = y * yd; - - for ( x = 0; x < size; x++ ) { - - cxy = cy + x; - - for ( z = 0; z < size; z++ ) - field[ zd * z + cxy ] += val; - - } - - } - - } - - }; - - this.addPlaneZ = function( strength, subtract ) { - - var x, y, z, zz, val, zdiv, cz, cyz; - - // cache attribute lookups - size = this.size, - yd = this.yd, - zd = this.zd, - field = this.field, - - dist = size * Math.sqrt( strength / subtract ); - - if ( dist > size ) dist = size; - - for ( z = 0; z < dist; z++ ) { - - zdiv = z / size; - zz = zdiv * zdiv; - val = strength / ( 0.0001 + zz ) - subtract; - if ( val > 0.0 ) { - - cz = zd * z; - - for ( y = 0; y < size; y++ ) { - - cyz = cz + y * yd; - - for ( x = 0; x < size; x++ ) - field[ cyz + x ] += val; - - } - - } - - } - - }; - - ///////////////////////////////////// - // Updates - ///////////////////////////////////// - - this.reset = function() { - - var i; - - // wipe the normal cache - - for ( i = 0; i < this.size3; i++ ) { - - this.normal_cache[ i * 3 ] = 0.0; - this.field[ i ] = 0.0; - - } - - }; - - this.render = function( render_callback ) { - - this.begin(); - - // Triangulate. Yeah, this is slow. - - var q, x, y, z, fx, fy, fz, y_offset, z_offset, smin2 = this.size - 2; - - for ( z = 1; z < smin2; z++ ) { - - z_offset = this.size2 * z; - fz = ( z - this.halfsize ) / this.halfsize; //+ 1 - - for ( y = 1; y < smin2; y++ ) { - - y_offset = z_offset + this.size * y; - fy = ( y - this.halfsize ) / this.halfsize; //+ 1 - - for ( x = 1; x < smin2; x++ ) { - - fx = ( x - this.halfsize ) / this.halfsize; //+ 1 - q = y_offset + x; - - this.polygonize( fx, fy, fz, q, this.isolation, render_callback ); - - } - - } - - } - - this.end( render_callback ); - - }; - - this.generateGeometry = function() { - - var start = 0, geo = new THREE.Geometry(); - var normals = []; - - var geo_callback = function( object ) { - - var i, x, y, z, vertex, position, normal, - face, a, b, c, na, nb, nc; - - - for ( i = 0; i < object.count; i++ ) { - - a = i * 3; - b = a + 1; - c = a + 2; - - x = object.positionArray[ a ]; - y = object.positionArray[ b ]; - z = object.positionArray[ c ]; - position = new THREE.Vector3( x, y, z ); - - x = object.normalArray[ a ]; - y = object.normalArray[ b ]; - z = object.normalArray[ c ]; - normal = new THREE.Vector3( x, y, z ); - normal.normalize(); - - vertex = new THREE.Vertex( position ); - - geo.vertices.push( vertex ); - normals.push( normal ); - - } - - nfaces = object.count / 3; - - for ( i = 0; i < nfaces; i++ ) { - - a = ( start + i ) * 3; - b = a + 1; - c = a + 2; - - na = normals[ a ]; - nb = normals[ b ]; - nc = normals[ c ]; - - face = new THREE.Face3( a, b, c, [ na, nb, nc ] ); - - geo.faces.push( face ); - - } - - start += nfaces; - object.count = 0; - - }; - - this.render( geo_callback ); - - // console.log( "generated " + geo.faces.length + " triangles" ); - - return geo; - - }; - - this.init( resolution ); - -}; - -THREE.MarchingCubes.prototype = new THREE.Object3D(); -THREE.MarchingCubes.prototype.constructor = THREE.MarchingCubes; - - -///////////////////////////////////// -// Marching cubes lookup tables -///////////////////////////////////// - -// These tables are straight from Paul Bourke's page: -// http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/ -// who in turn got them from Cory Gene Bloyd. - -THREE.edgeTable = new Int32Array([ -0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, -0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, -0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, -0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, -0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, -0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, -0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, -0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, -0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, -0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, -0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, -0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, -0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, -0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, -0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , -0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, -0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, -0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, -0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, -0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, -0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, -0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, -0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, -0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, -0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, -0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, -0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, -0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, -0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, -0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, -0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, -0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0]) - -THREE.triTable = new Int32Array([ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1, -3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1, -3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1, -3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1, -9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1, -8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1, -9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1, -3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1, -1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1, -4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1, -4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1, -9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1, -1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, -5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1, -2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1, -9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, -0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1, -10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1, -5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1, -5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1, -0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1, -10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1, -8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1, -2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1, -2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1, -11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1, -9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1, -5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1, -11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1, -11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1, -9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1, -5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1, -2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1, -6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1, -0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1, -3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1, -6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1, -5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1, -1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1, -6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1, -8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1, -7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1, -3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1, -0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1, -8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1, -5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1, -0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1, -6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1, -10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1, -8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1, -1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1, -3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1, -0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1, -0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1, -3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1, -6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1, -9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1, -8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1, -3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1, -6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1, -10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1, -10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1, -2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1, -7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1, -7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1, -2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1, -1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1, -11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1, -8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1, -0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1, -7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1, -7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1, -2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1, -10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1, -10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1, -0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1, -7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1, -6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1, -8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1, -9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1, -6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1, -4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1, -10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1, -8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1, -1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1, -8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1, -10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1, -4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1, -10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1, -9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1, -7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1, -3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1, -7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1, -9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1, -3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1, -6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1, -9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1, -1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1, -4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1, -7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1, -6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1, -3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1, -0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1, -6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1, -0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1, -11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1, -6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1, -5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1, -9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1, -1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1, -10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1, -0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1, -5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1, -10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1, -11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1, -0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1, -9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1, -7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1, -2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1, -9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1, -9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1, -1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1, -9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1, -9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1, -0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1, -10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1, -2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1, -0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1, -0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1, -9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1, -5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1, -3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1, -5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1, -8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1, -0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1, -9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1, -0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1, -1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1, -3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1, -4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1, -9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1, -11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1, -11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1, -2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1, -9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1, -3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1, -1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1, -4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1, -4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1, -0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1, -3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1, -3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1, -0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1, -9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1, -1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]); -/** - * @author sroucheray / http://sroucheray.org/ - */ - -/** - * @constructor - * Three axis representing the cartesian coordinates - * @param xAxisColor {number} - * @param yAxisColor {number} - * @param zAxisColor {number} - * @param showArrows {Boolean} - * @param length {number} - * @param scale {number} - * - * @see THREE.Trident.defaultParams - */ -THREE.Trident = function ( params /** Object */) { - - THREE.Object3D.call( this ); - - var hPi = Math.PI / 2, cone; - - params = params || THREE.Trident.defaultParams; - - if(params !== THREE.Trident.defaultParams){ - for ( var key in THREE.Trident.defaultParams) { - if(!params.hasOwnProperty(key)){ - params[key] = THREE.Trident.defaultParams[key]; - } - } - } - - this.scale = new THREE.Vector3( params.scale, params.scale, params.scale ); - this.addChild( getSegment( new THREE.Vector3(params.length,0,0), params.xAxisColor ) ); - this.addChild( getSegment( new THREE.Vector3(0,params.length,0), params.yAxisColor ) ); - this.addChild( getSegment( new THREE.Vector3(0,0,params.length), params.zAxisColor ) ); - - if(params.showArrows){ - cone = getCone(params.xAxisColor); - cone.rotation.y = - hPi; - cone.position.x = params.length; - this.addChild( cone ); - - cone = getCone(params.yAxisColor); - cone.rotation.x = hPi; - cone.position.y = params.length; - this.addChild( cone ); - - cone = getCone(params.zAxisColor); - cone.rotation.y = Math.PI; - cone.position.z = params.length; - this.addChild( cone ); - } - - function getCone ( color ) { - //0.1 required to get a cone with a mapped bottom face - return new THREE.Mesh( new THREE.CylinderGeometry( 30, 0.1, params.length / 20, params.length / 5 ), new THREE.MeshBasicMaterial( { color : color } ) ); - } - - function getSegment ( point, color ){ - var geom = new THREE.Geometry(); - geom.vertices = [new THREE.Vertex(), new THREE.Vertex(point)]; - return new THREE.Line( geom, new THREE.LineBasicMaterial( { color : color } ) ); - } -}; - -THREE.Trident.prototype = new THREE.Object3D(); -THREE.Trident.prototype.constructor = THREE.Trident; - -THREE.Trident.defaultParams = { - xAxisColor : 0xFF0000, - yAxisColor : 0x00FF00, - zAxisColor : 0x0000FF, - showArrows : true, - length : 100, - scale : 1 -}; -/** - * @author bartek drozdz / http://everyday3d.com/ - */ - -THREE.PlaneCollider = function( point, normal ) { - - this.point = point; - this.normal = normal; - -}; - - -THREE.SphereCollider = function( center, radius ) { - - this.center = center; - this.radius = radius; - this.radiusSq = radius * radius; - -}; - -THREE.BoxCollider = function( min, max ) { - - this.min = min; - this.max = max; - this.dynamic = true; - - this.normal = new THREE.Vector3(); - -}; - -THREE.MeshCollider = function( mesh, box ) { - - this.mesh = mesh; - this.box = box; - this.numFaces = this.mesh.geometry.faces.length; - - this.normal = new THREE.Vector3(); - -}; - -THREE.CollisionSystem = function() { - - this.collisionNormal = new THREE.Vector3(); - this.colliders = []; - this.hits = []; - - // console.log("Collision system init / 004"); - -}; - -THREE.Collisions = new THREE.CollisionSystem(); - -THREE.CollisionSystem.prototype.merge = function( collisionSystem ) { - - this.colliders = this.colliders.concat( collisionSystem.colliders ); - this.hits = this.hits.concat( collisionSystem.hits ); - -}; - -THREE.CollisionSystem.prototype.rayCastAll = function( ray ) { - - ray.direction.normalize(); - - this.hits.length = 0; - - var i, l, d, collider, - ld = 0; - - for ( i = 0, l = this.colliders.length; i < l; i++ ) { - - collider = this.colliders[ i ]; - - d = this.rayCast( ray, collider ); - - if ( d < Number.MAX_VALUE ) { - - collider.distance = d; - - if ( d > ld ) - this.hits.push( collider ); - else - this.hits.unshift( collider ); - - ld = d; - - } - - } - - return this.hits; - -}; - -THREE.CollisionSystem.prototype.rayCastNearest = function( ray ) { - - var cs = this.rayCastAll( ray ); - - if( cs.length == 0 ) return null; - - var i = 0; - - while( cs[ i ] instanceof THREE.MeshCollider ) { - - var dist_index = this.rayMesh ( ray, cs[ i ] ); - - if( dist_index.dist < Number.MAX_VALUE ) { - - cs[ i ].distance = dist_index.dist; - cs[ i ].faceIndex = dist_index.faceIndex; - break; - - } - - i++; - - } - - if ( i > cs.length ) return null; - - return cs[ i ]; - -}; - -THREE.CollisionSystem.prototype.rayCast = function( ray, collider ) { - - if ( collider instanceof THREE.PlaneCollider ) - return this.rayPlane( ray, collider ); - - else if ( collider instanceof THREE.SphereCollider ) - return this.raySphere( ray, collider ); - - else if ( collider instanceof THREE.BoxCollider ) - return this.rayBox( ray, collider ); - - else if ( collider instanceof THREE.MeshCollider && collider.box ) - return this.rayBox( ray, collider.box ); - -}; - -THREE.CollisionSystem.prototype.rayMesh = function( r, me ) { - - var rt = this.makeRayLocal( r, me.mesh ); - - var d = Number.MAX_VALUE; - var nearestface; - - for( var i = 0; i < me.numFaces; i++ ) { - var face = me.mesh.geometry.faces[i]; - var p0 = me.mesh.geometry.vertices[ face.a ].position; - var p1 = me.mesh.geometry.vertices[ face.b ].position; - var p2 = me.mesh.geometry.vertices[ face.c ].position; - var p3 = face instanceof THREE.Face4 ? me.mesh.geometry.vertices[ face.d ].position : null; - - if (face instanceof THREE.Face3) { - var nd = this.rayTriangle( rt, p0, p1, p2, d, this.collisionNormal ); - - if( nd < d ) { - - d = nd; - nearestface = i; - me.normal.copy( this.collisionNormal ); - me.normal.normalize(); - - } - - } - - else if (face instanceof THREE.Face4) { - - var nd = this.rayTriangle( rt, p0, p1, p3, d, this.collisionNormal ); - - if( nd < d ) { - - d = nd; - nearestface = i; - me.normal.copy( this.collisionNormal ); - me.normal.normalize(); - - } - - nd = this.rayTriangle( rt, p1, p2, p3, d, this.collisionNormal ); - - if( nd < d ) { - - d = nd; - nearestface = i; - me.normal.copy( this.collisionNormal ); - me.normal.normalize(); - - } - - } - - } - - return {dist: d, faceIndex: nearestface}; - -}; - -THREE.CollisionSystem.prototype.rayTriangle = function( ray, p0, p1, p2, mind, n ) { - - var e1 = THREE.CollisionSystem.__v1, - e2 = THREE.CollisionSystem.__v2; - - n.set( 0, 0, 0 ); - - // do not crash on quads, fail instead - - e1.sub( p1, p0 ); - e2.sub( p2, p1 ); - n.cross( e1, e2 ) - - var dot = n.dot( ray.direction ); - if ( !( dot < 0 ) ) return Number.MAX_VALUE; - - var d = n.dot( p0 ); - var t = d - n.dot( ray.origin ); - - if ( !( t <= 0 ) ) return Number.MAX_VALUE; - if ( !( t >= dot * mind ) ) return Number.MAX_VALUE; - - t = t / dot; - - var p = THREE.CollisionSystem.__v3; - - p.copy( ray.direction ); - p.multiplyScalar( t ); - p.addSelf( ray.origin ); - - var u0, u1, u2, v0, v1, v2; - - if ( Math.abs( n.x ) > Math.abs( n.y ) ) { - - if ( Math.abs( n.x ) > Math.abs( n.z ) ) { - - u0 = p.y - p0.y; - u1 = p1.y - p0.y; - u2 = p2.y - p0.y; - - v0 = p.z - p0.z; - v1 = p1.z - p0.z; - v2 = p2.z - p0.z; - - } else { - - u0 = p.x - p0.x; - u1 = p1.x - p0.x; - u2 = p2.x - p0.x; - - v0 = p.y - p0.y; - v1 = p1.y - p0.y; - v2 = p2.y - p0.y; - - } - - } else { - - if( Math.abs( n.y ) > Math.abs( n.z ) ) { - - u0 = p.x - p0.x; - u1 = p1.x - p0.x; - u2 = p2.x - p0.x; - - v0 = p.z - p0.z; - v1 = p1.z - p0.z; - v2 = p2.z - p0.z; - - } else { - - u0 = p.x - p0.x; - u1 = p1.x - p0.x; - u2 = p2.x - p0.x; - - v0 = p.y - p0.y; - v1 = p1.y - p0.y; - v2 = p2.y - p0.y; - - } - - } - - var temp = u1 * v2 - v1 * u2; - if( !(temp != 0) ) return Number.MAX_VALUE; - //console.log("temp: " + temp); - temp = 1 / temp; - - var alpha = ( u0 * v2 - v0 * u2 ) * temp; - if( !(alpha >= 0) ) return Number.MAX_VALUE; - //console.log("alpha: " + alpha); - - var beta = ( u1 * v0 - v1 * u0 ) * temp; - if( !(beta >= 0) ) return Number.MAX_VALUE; - //console.log("beta: " + beta); - - var gamma = 1 - alpha - beta; - if( !(gamma >= 0) ) return Number.MAX_VALUE; - //console.log("gamma: " + gamma); - - return t; - -}; - -THREE.CollisionSystem.prototype.makeRayLocal = function( ray, m ) { - - var mt = THREE.CollisionSystem.__m; - THREE.Matrix4.makeInvert( m.matrixWorld, mt ); - - var rt = THREE.CollisionSystem.__r; - rt.origin.copy( ray.origin ); - rt.direction.copy( ray.direction ); - - mt.multiplyVector3( rt.origin ); - mt.rotateAxis( rt.direction ); - rt.direction.normalize(); - //m.localRay = rt; - - return rt; - -}; - -THREE.CollisionSystem.prototype.rayBox = function( ray, ab ) { - - var rt; - - if ( ab.dynamic && ab.mesh && ab.mesh.matrixWorld ) { - - rt = this.makeRayLocal( ray, ab.mesh ); - - } else { - - rt = THREE.CollisionSystem.__r; - rt.origin.copy( ray.origin ); - rt.direction.copy( ray.direction ); - - } - - var xt = 0, yt = 0, zt = 0; - var xn = 0, yn = 0, zn = 0; - var ins = true; - - if( rt.origin.x < ab.min.x ) { - - xt = ab.min.x - rt.origin.x; - //if(xt > ray.direction.x) return return Number.MAX_VALUE; - xt /= rt.direction.x; - ins = false; - xn = -1; - - } else if( rt.origin.x > ab.max.x ) { - - xt = ab.max.x - rt.origin.x; - //if(xt < ray.direction.x) return return Number.MAX_VALUE; - xt /= rt.direction.x; - ins = false; - xn = 1; - - } - - if( rt.origin.y < ab.min.y ) { - - yt = ab.min.y - rt.origin.y; - //if(yt > ray.direction.y) return return Number.MAX_VALUE; - yt /= rt.direction.y; - ins = false; - yn = -1; - - } else if( rt.origin.y > ab.max.y ) { - - yt = ab.max.y - rt.origin.y; - //if(yt < ray.direction.y) return return Number.MAX_VALUE; - yt /= rt.direction.y; - ins = false; - yn = 1; - - } - - if( rt.origin.z < ab.min.z ) { - - zt = ab.min.z - rt.origin.z; - //if(zt > ray.direction.z) return return Number.MAX_VALUE; - zt /= rt.direction.z; - ins = false; - zn = -1; - - } else if( rt.origin.z > ab.max.z ) { - - zt = ab.max.z - rt.origin.z; - //if(zt < ray.direction.z) return return Number.MAX_VALUE; - zt /= rt.direction.z; - ins = false; - zn = 1; - - } - - if( ins ) return -1; - - var which = 0; - var t = xt; - - if( yt > t ) { - - which = 1; - t = yt; - - } - - if ( zt > t ) { - - which = 2; - t = zt; - - } - - switch( which ) { - - case 0: - - var y = rt.origin.y + rt.direction.y * t; - if ( y < ab.min.y || y > ab.max.y ) return Number.MAX_VALUE; - var z = rt.origin.z + rt.direction.z * t; - if ( z < ab.min.z || z > ab.max.z ) return Number.MAX_VALUE; - ab.normal.set( xn, 0, 0 ); - break; - - case 1: - - var x = rt.origin.x + rt.direction.x * t; - if ( x < ab.min.x || x > ab.max.x ) return Number.MAX_VALUE; - var z = rt.origin.z + rt.direction.z * t; - if ( z < ab.min.z || z > ab.max.z ) return Number.MAX_VALUE; - ab.normal.set( 0, yn, 0) ; - break; - - case 2: - - var x = rt.origin.x + rt.direction.x * t; - if ( x < ab.min.x || x > ab.max.x ) return Number.MAX_VALUE; - var y = rt.origin.y + rt.direction.y * t; - if ( y < ab.min.y || y > ab.max.y ) return Number.MAX_VALUE; - ab.normal.set( 0, 0, zn ); - break; - - } - - return t; - -}; - -THREE.CollisionSystem.prototype.rayPlane = function( r, p ) { - - var t = r.direction.dot( p.normal ); - var d = p.point.dot( p.normal ); - var ds; - - if( t < 0 ) ds = ( d - r.origin.dot( p.normal ) ) / t; - else return Number.MAX_VALUE; - - if( ds > 0 ) return ds; - else return Number.MAX_VALUE; - -}; - -THREE.CollisionSystem.prototype.raySphere = function( r, s ) { - - var e = s.center.clone().subSelf( r.origin ); - if ( e.lengthSq < s.radiusSq ) return -1; - - var a = e.dot( r.direction.clone() ); - if ( a <= 0 ) return Number.MAX_VALUE; - - var t = s.radiusSq - ( e.lengthSq() - a * a ); - if ( t >= 0 ) return Math.abs( a ) - Math.sqrt( t ); - - return Number.MAX_VALUE; - -}; - -THREE.CollisionSystem.__v1 = new THREE.Vector3(); -THREE.CollisionSystem.__v2 = new THREE.Vector3(); -THREE.CollisionSystem.__v3 = new THREE.Vector3(); -THREE.CollisionSystem.__nr = new THREE.Vector3(); -THREE.CollisionSystem.__m = new THREE.Matrix4(); -THREE.CollisionSystem.__r = new THREE.Ray(); -/** - * @author bartek drozdz / http://everyday3d.com/ - */ - -THREE.CollisionUtils = {}; - -// @params m THREE.Mesh -// @returns CBox dynamic Object Bounding Box - -THREE.CollisionUtils.MeshOBB = function( m ) { - - m.geometry.computeBoundingBox(); - var b = m.geometry.boundingBox; - var min = new THREE.Vector3( b.x[0], b.y[0], b.z[0] ); - var max = new THREE.Vector3( b.x[1], b.y[1], b.z[1] ); - var box = new THREE.BoxCollider( min, max ); - box.mesh = m; - return box; - -} - -// @params m THREE.Mesh -// @returns CBox static Axis-Aligned Bounding Box -// -// The AABB is calculated based on current -// position of the object (assumes it won't move) - -THREE.CollisionUtils.MeshAABB = function( m ) { - - var box = THREE.CollisionUtils.MeshOBB( m ); - box.min.addSelf( m.position ); - box.max.addSelf( m.position ); - box.dynamic = false; - return box; - -}; - -// @params m THREE.Mesh -// @returns CMesh with aOOB attached (that speeds up intersection tests) - -THREE.CollisionUtils.MeshColliderWBox = function( m ) { - - var mc = new THREE.MeshCollider( m, THREE.CollisionUtils.MeshOBB( m ) ); - - return mc; - -}; -/** - * @author mrdoob / http://mrdoob.com/ - * @author marklundin / http://mark-lundin.com/ - */ - -if ( THREE.WebGLRenderer ) { - - THREE.AnaglyphWebGLRenderer = function ( parameters ) { - - THREE.WebGLRenderer.call( this, parameters ); - - var _this = this, _setSize = this.setSize, _render = this.render; - var _cameraL = new THREE.Camera(), _cameraR = new THREE.Camera(); - var eyeRight = new THREE.Matrix4(), - eyeLeft = new THREE.Matrix4(), - focalLength = 125, - aspect, near, fov; - - _cameraL.useTarget = _cameraR.useTarget = false; - _cameraL.matrixAutoUpdate = _cameraR.matrixAutoUpdate = false; - - var _params = { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat }; - var _renderTargetL = new THREE.WebGLRenderTarget( 512, 512, _params ), _renderTargetR = new THREE.WebGLRenderTarget( 512, 512, _params ); - - var _camera = new THREE.Camera( 53, 1, 1, 10000 ); - _camera.position.z = 2; - - _material = new THREE.MeshShaderMaterial( { - - uniforms: { - - "mapLeft": { type: "t", value: 0, texture: _renderTargetL }, - "mapRight": { type: "t", value: 1, texture: _renderTargetR } - - }, - vertexShader: [ - - "varying vec2 vUv;", - - "void main() {", - - "vUv = vec2( uv.x, 1.0 - uv.y );", - "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", - - "}" - - ].join("\n"), - fragmentShader: [ - - "uniform sampler2D mapLeft;", - "uniform sampler2D mapRight;", - "varying vec2 vUv;", - - "void main() {", - - "vec4 colorL, colorR;", - "vec2 uv = vUv;", - - "colorL = texture2D( mapLeft, uv );", - "colorR = texture2D( mapRight, uv );", - - // http://3dtv.at/Knowhow/AnaglyphComparison_en.aspx - - "gl_FragColor = vec4( colorL.g * 0.7 + colorL.b * 0.3, colorR.g, colorR.b, colorL.a + colorR.a ) * 1.1;", - - "}" - - ].join("\n") - - } ); - - var _scene = new THREE.Scene(); - _scene.addObject( new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), _material ) ); - - this.setSize = function ( width, height ) { - - _setSize.call( _this, width, height ); - - _renderTargetL.width = width; - _renderTargetL.height = height; - - _renderTargetR.width = width; - _renderTargetR.height = height; - - }; - - /* - * Renderer now uses an asymmetric perspective projection (http://paulbourke.net/miscellaneous/stereographics/stereorender/). - * Each camera is offset by the eye seperation and its projection matrix is also skewed asymetrically back to converge on the same - * projection plane. Added a focal length parameter to, this is where the parallax is equal to 0. - */ - this.render = function ( scene, camera, renderTarget, forceClear ) { - - - camera.update( null, true ); - - var hasCameraChanged = aspect !== camera.aspect || near !== camera.near || fov !== camera.fov; - - if( hasCameraChanged ) { - - aspect = camera.aspect; - near = camera.near; - fov = camera.fov; - - var projectionMatrix = camera.projectionMatrix.clone(), - eyeSep = focalLength / 30 * 0.5, - eyeSepOnProjection = eyeSep * near / focalLength, - ymax = near * Math.tan( fov * Math.PI / 360 ), - xmin, xmax; - - //translate xOffset - eyeRight.n14 = eyeSep; - eyeLeft.n14 = -eyeSep; - - //For left eye - xmin = -ymax * aspect + eyeSepOnProjection; - xmax = ymax * aspect + eyeSepOnProjection; - projectionMatrix.n11 = 2 * near / ( xmax - xmin ); - projectionMatrix.n13 = ( xmax + xmin ) / ( xmax - xmin ); - _cameraL.projectionMatrix = projectionMatrix.clone(); - - //for right eye - xmin = -ymax * aspect - eyeSepOnProjection; - xmax = ymax * aspect - eyeSepOnProjection; - projectionMatrix.n11 = 2 * near / ( xmax - xmin ); - projectionMatrix.n13 = ( xmax + xmin ) / ( xmax - xmin ); - _cameraR.projectionMatrix = projectionMatrix.clone(); - - } - - _cameraL.matrix = camera.matrixWorld.clone().multiplySelf( eyeLeft ); - _cameraL.update(null, true); - _cameraL.position.copy( camera.position ); - _cameraL.near = near; - _cameraL.far = camera.far; - _render.call( _this, scene, _cameraL, _renderTargetL, true ); - - _cameraR.matrix = camera.matrixWorld.clone().multiplySelf( eyeRight ); - _cameraR.update(null, true); - _cameraR.position.copy( camera.position ); - _cameraR.near = near; - _cameraR.far = camera.far; - _render.call( _this, scene, _cameraR, _renderTargetR, true ); - - _render.call( _this, _scene, _camera ); - - }; - - }; - -} -/** - * @author alteredq / http://alteredqualia.com/ - */ - -if ( THREE.WebGLRenderer ) { - - THREE.CrosseyedWebGLRenderer = function ( parameters ) { - - THREE.WebGLRenderer.call( this, parameters ); - - this.autoClear = false; - - var _this = this, _setSize = this.setSize, _render = this.render; - - var _width, _height; - - var _cameraL = new THREE.Camera(), - _cameraR = new THREE.Camera(); - - _this.separation = 10; - if ( parameters && parameters.separation !== undefined ) _this.separation = parameters.separation; - - var SCREEN_WIDTH = window.innerWidth; - var SCREEN_HEIGHT = window.innerHeight; - var HALF_WIDTH = SCREEN_WIDTH / 2; - - var _camera = new THREE.Camera( 53, HALF_WIDTH / SCREEN_HEIGHT, 1, 10000 ); - _camera.position.z = -10; - - - this.setSize = function ( width, height ) { - - _setSize.call( _this, width, height ); - - _width = width/2; - _height = height; - - }; - - this.render = function ( scene, camera, renderTarget, forceClear ) { - - this.clear(); - - _cameraL.fov = camera.fov; - _cameraL.aspect = 0.5 * camera.aspect; - _cameraL.near = camera.near; - _cameraL.far = camera.far; - _cameraL.updateProjectionMatrix(); - - _cameraL.position.copy( camera.position ); - _cameraL.target.position.copy( camera.target.position ); - _cameraL.translateX( _this.separation ); - - _cameraR.projectionMatrix = _cameraL.projectionMatrix; - - _cameraR.position.copy( camera.position ); - _cameraR.target.position.copy( camera.target.position ); - _cameraR.translateX( - _this.separation ); - - this.setViewport( 0, 0, _width, _height ); - _render.call( _this, scene, _cameraL ); - - this.setViewport( _width, 0, _width, _height ); - _render.call( _this, scene, _cameraR, false ); - - }; - - }; - -} +var THREE=THREE||{};if(!window.Int32Array)window.Int32Array=Array,window.Float32Array=Array;THREE.Color=function(b){this.setHex(b)}; +THREE.Color.prototype={copy:function(b){this.r=b.r;this.g=b.g;this.b=b.b;this.hex=b.hex},setHex:function(b){this.hex=~~b&16777215;this.updateRGB()},setRGB:function(b,c,d){this.r=b;this.g=c;this.b=d;this.updateHex()},setHSV:function(b,c,d){var e,f,g,j,k,m;if(d==0)e=f=g=0;else switch(j=Math.floor(b*6),k=b*6-j,b=d*(1-c),m=d*(1-c*k),c=d*(1-c*(1-k)),j){case 1:e=m;f=d;g=b;break;case 2:e=b;f=d;g=c;break;case 3:e=b;f=m;g=d;break;case 4:e=c;f=b;g=d;break;case 5:e=d;f=b;g=m;break;case 6:case 0:e=d,f=c,g=b}this.setRGB(e, +f,g)},updateHex:function(){this.hex=~~(this.r*255)<<16^~~(this.g*255)<<8^~~(this.b*255)},updateRGB:function(){this.r=(this.hex>>16&255)/255;this.g=(this.hex>>8&255)/255;this.b=(this.hex&255)/255},clone:function(){return new THREE.Color(this.hex)}};THREE.Vector2=function(b,c){this.set(b||0,c||0)}; +THREE.Vector2.prototype={set:function(b,c){this.x=b;this.y=c;return this},copy:function(b){this.x=b.x;this.y=b.y;return this},clone:function(){return new THREE.Vector2(this.x,this.y)},add:function(b,c){this.x=b.x+c.x;this.y=b.y+c.y;return this},addSelf:function(b){this.x+=b.x;this.y+=b.y;return this},sub:function(b,c){this.x=b.x-c.x;this.y=b.y-c.y;return this},subSelf:function(b){this.x-=b.x;this.y-=b.y;return this},multiplyScalar:function(b){this.x*=b;this.y*=b;return this},divideScalar:function(b){b? +(this.x/=b,this.y/=b):this.set(0,0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(b){return this.x*b.x+this.y*b.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(b){return Math.sqrt(this.distanceToSquared(b))},distanceToSquared:function(b){var c=this.x-b.x,b=this.y-b.y;return c*c+b*b},setLength:function(b){return this.normalize().multiplyScalar(b)}, +unit:function(){return this.normalize()},equals:function(b){return b.x==this.x&&b.y==this.y}};THREE.Vector3=function(b,c,d){this.set(b||0,c||0,d||0)}; +THREE.Vector3.prototype={set:function(b,c,d){this.x=b;this.y=c;this.z=d;return this},copy:function(b){this.x=b.x;this.y=b.y;this.z=b.z;return this},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)},add:function(b,c){this.x=b.x+c.x;this.y=b.y+c.y;this.z=b.z+c.z;return this},addSelf:function(b){this.x+=b.x;this.y+=b.y;this.z+=b.z;return this},addScalar:function(b){this.x+=b;this.y+=b;this.z+=b;return this},sub:function(b,c){this.x=b.x-c.x;this.y=b.y-c.y;this.z=b.z-c.z;return this},subSelf:function(b){this.x-= +b.x;this.y-=b.y;this.z-=b.z;return this},multiply:function(b,c){this.x=b.x*c.x;this.y=b.y*c.y;this.z=b.z*c.z;return this},multiplySelf:function(b){this.x*=b.x;this.y*=b.y;this.z*=b.y;return this},multiplyScalar:function(b){this.x*=b;this.y*=b;this.z*=b;return this},divideSelf:function(b){return this.divide(this,b)},divideScalar:function(b){b?(this.x/=b,this.y/=b,this.z/=b):this.set(0,0,0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(b){return this.x*b.x+this.y*b.y+this.z* +b.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return this.x+this.y+this.z},normalize:function(){return this.divideScalar(this.length())},setLength:function(b){return this.normalize().multiplyScalar(b)},cross:function(b,c){this.x=b.y*c.z-b.z*c.y;this.y=b.z*c.x-b.x*c.z;this.z=b.x*c.y-b.y*c.x;return this},crossSelf:function(b){return this.set(this.y*b.z-this.z*b.y,this.z*b.x-this.x*b.z,this.x* +b.y-this.y*b.x)},distanceTo:function(b){return Math.sqrt(this.distanceToSquared(b))},distanceToSquared:function(b){return(new THREE.Vector3).sub(this,b).lengthSq()},setPositionFromMatrix:function(b){this.x=b.n14;this.y=b.n24;this.z=b.n34},setRotationFromMatrix:function(b){var c=Math.cos(this.y);this.y=Math.asin(b.n13);Math.abs(c)>1.0E-5?(this.x=Math.atan2(-b.n23/c,b.n33/c),this.z=Math.atan2(-b.n12/c,b.n11/c)):(this.x=0,this.z=Math.atan2(b.n21,b.n22))},isZero:function(){return this.lengthSq()<1.0E-4}}; +THREE.Vector4=function(b,c,d,e){this.set(b||0,c||0,d||0,e||1)}; +THREE.Vector4.prototype={set:function(b,c,d,e){this.x=b;this.y=c;this.z=d;this.w=e;return this},copy:function(b){return this.set(b.x,b.y,b.z,b.w||1)},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)},add:function(b,c){this.x=b.x+c.x;this.y=b.y+c.y;this.z=b.z+c.z;this.w=b.w+c.w;return this},addSelf:function(b){this.x+=b.x;this.y+=b.y;this.z+=b.z;this.w+=b.w;return this},sub:function(b,c){this.x=b.x-c.x;this.y=b.y-c.y;this.z=b.z-c.z;this.w=b.w-c.w;return this},subSelf:function(b){this.x-= +b.x;this.y-=b.y;this.z-=b.z;this.w-=b.w;return this},multiplyScalar:function(b){this.x*=b;this.y*=b;this.z*=b;this.w*=b;return this},divideScalar:function(b){b?(this.x/=b,this.y/=b,this.z/=b,this.w/=b):this.set(0,0,0,1);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(b){return this.x*b.x+this.y*b.y+this.z*b.z+this.w*b.w},lengthSq:function(){return this.dot(this)},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())}, +setLength:function(b){return this.normalize().multiplyScalar(b)},lerpSelf:function(b,c){this.x+=(b.x-this.x)*c;this.y+=(b.y-this.y)*c;this.z+=(b.z-this.z)*c;this.w+=(b.w-this.w)*c;return this}};THREE.Ray=function(b,c){this.origin=b||new THREE.Vector3;this.direction=c||new THREE.Vector3}; +THREE.Ray.prototype={intersectScene:function(b){return this.intersectObjects(b.objects)},intersectObjects:function(b){var c,d,e=[];c=0;for(d=b.length;c0&&b>0&&g+b<1}if(b instanceof THREE.Particle){var e=c(this.origin,this.direction,b);if(!e||e>b.scale.x)return[];return[{distance:e,point:b.position,face:null,object:b}]}else if(b instanceof THREE.Mesh){e=c(this.origin,this.direction,b);if(!e||e>b.geometry.boundingSphere.radius*Math.max(b.scale.x,Math.max(b.scale.y,b.scale.z)))return[];var f,g,j,k,m,o,n,t,p,u,v=b.geometry, +z=v.vertices,C=[],e=0;for(f=v.faces.length;e0:t<0))if(n=n.dot((new THREE.Vector3).sub(j,p))/t,p=p.addSelf(u.multiplyScalar(n)), +g instanceof THREE.Face3)d(p,j,k,m)&&(g={distance:this.origin.distanceTo(p),point:p,face:g,object:b},C.push(g));else if(g instanceof THREE.Face4&&(d(p,j,k,o)||d(p,k,m,o)))g={distance:this.origin.distanceTo(p),point:p,face:g,object:b},C.push(g);return C}else return[]}}; +THREE.Rectangle=function(){function b(){g=e-c;j=f-d}var c,d,e,f,g,j,k=!0;this.getX=function(){return c};this.getY=function(){return d};this.getWidth=function(){return g};this.getHeight=function(){return j};this.getLeft=function(){return c};this.getTop=function(){return d};this.getRight=function(){return e};this.getBottom=function(){return f};this.set=function(g,j,n,t){k=!1;c=g;d=j;e=n;f=t;b()};this.addPoint=function(g,j){k?(k=!1,c=g,d=j,e=g,f=j):(c=cg?e:g,f=f>j?f:j);b()};this.add3Points= +function(g,j,n,t,p,u){k?(k=!1,c=gn?g>p?g:p:n>p?n:p,f=j>t?j>u?j:u:t>u?t:u):(c=gn?g>p?g>e?g:e:p>e?p:e:n>p?n>e?n:e:p>e?p:e,f=j>t?j>u?j>f?j:f:u>f?u:f:t>u?t>f?t:f:u>f?u:f);b()};this.addRectangle=function(g){k?(k=!1,c=g.getLeft(),d=g.getTop(),e=g.getRight(),f=g.getBottom()):(c=cg.getRight()?e:g.getRight(),f=f> +g.getBottom()?f:g.getBottom());b()};this.inflate=function(g){c-=g;d-=g;e+=g;f+=g;b()};this.minSelf=function(g){c=c>g.getLeft()?c:g.getLeft();d=d>g.getTop()?d:g.getTop();e=e=0&&Math.min(f,b.getBottom())-Math.max(d,b.getTop())>=0};this.empty=function(){k=!0;f=e=d=c=0;b()};this.isEmpty=function(){return k}};THREE.Matrix3=function(){this.m=[]}; +THREE.Matrix3.prototype={transpose:function(){var b,c=this.m;b=c[1];c[1]=c[3];c[3]=b;b=c[2];c[2]=c[6];c[6]=b;b=c[5];c[5]=c[7];c[7]=b;return this},transposeIntoArray:function(b){var c=this.m;b[0]=c[0];b[1]=c[3];b[2]=c[6];b[3]=c[1];b[4]=c[4];b[5]=c[7];b[6]=c[2];b[7]=c[5];b[8]=c[8];return this}};THREE.Matrix4=function(b,c,d,e,f,g,j,k,m,o,n,t,p,u,v,z){this.set(b||1,c||0,d||0,e||0,f||0,g||1,j||0,k||0,m||0,o||0,n||1,t||0,p||0,u||0,v||0,z||1);this.flat=Array(16);this.m33=new THREE.Matrix3}; +THREE.Matrix4.prototype={set:function(b,c,d,e,f,g,j,k,m,o,n,t,p,u,v,z){this.n11=b;this.n12=c;this.n13=d;this.n14=e;this.n21=f;this.n22=g;this.n23=j;this.n24=k;this.n31=m;this.n32=o;this.n33=n;this.n34=t;this.n41=p;this.n42=u;this.n43=v;this.n44=z;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(b){this.set(b.n11,b.n12,b.n13,b.n14,b.n21,b.n22,b.n23,b.n24,b.n31,b.n32,b.n33,b.n34,b.n41,b.n42,b.n43,b.n44);return this},lookAt:function(b,c,d){var e=THREE.Matrix4.__v1, +f=THREE.Matrix4.__v2,g=THREE.Matrix4.__v3;g.sub(b,c).normalize();if(g.length()===0)g.z=1;e.cross(d,g).normalize();e.length()===0&&(g.x+=1.0E-4,e.cross(d,g).normalize());f.cross(g,e).normalize();this.n11=e.x;this.n12=f.x;this.n13=g.x;this.n21=e.y;this.n22=f.y;this.n23=g.y;this.n31=e.z;this.n32=f.z;this.n33=g.z;return this},multiplyVector3:function(b){var c=b.x,d=b.y,e=b.z,f=1/(this.n41*c+this.n42*d+this.n43*e+this.n44);b.x=(this.n11*c+this.n12*d+this.n13*e+this.n14)*f;b.y=(this.n21*c+this.n22*d+this.n23* +e+this.n24)*f;b.z=(this.n31*c+this.n32*d+this.n33*e+this.n34)*f;return b},multiplyVector4:function(b){var c=b.x,d=b.y,e=b.z,f=b.w;b.x=this.n11*c+this.n12*d+this.n13*e+this.n14*f;b.y=this.n21*c+this.n22*d+this.n23*e+this.n24*f;b.z=this.n31*c+this.n32*d+this.n33*e+this.n34*f;b.w=this.n41*c+this.n42*d+this.n43*e+this.n44*f;return b},rotateAxis:function(b){var c=b.x,d=b.y,e=b.z;b.x=c*this.n11+d*this.n12+e*this.n13;b.y=c*this.n21+d*this.n22+e*this.n23;b.z=c*this.n31+d*this.n32+e*this.n33;b.normalize(); +return b},crossVector:function(b){var c=new THREE.Vector4;c.x=this.n11*b.x+this.n12*b.y+this.n13*b.z+this.n14*b.w;c.y=this.n21*b.x+this.n22*b.y+this.n23*b.z+this.n24*b.w;c.z=this.n31*b.x+this.n32*b.y+this.n33*b.z+this.n34*b.w;c.w=b.w?this.n41*b.x+this.n42*b.y+this.n43*b.z+this.n44*b.w:1;return c},multiply:function(b,c){var d=b.n11,e=b.n12,f=b.n13,g=b.n14,j=b.n21,k=b.n22,m=b.n23,o=b.n24,n=b.n31,t=b.n32,p=b.n33,u=b.n34,v=b.n41,z=b.n42,C=b.n43,A=b.n44,I=c.n11,y=c.n12,G=c.n13,F=c.n14,B=c.n21,M=c.n22, +L=c.n23,O=c.n24,w=c.n31,W=c.n32,S=c.n33,T=c.n34,h=c.n41,R=c.n42,J=c.n43,P=c.n44;this.n11=d*I+e*B+f*w+g*h;this.n12=d*y+e*M+f*W+g*R;this.n13=d*G+e*L+f*S+g*J;this.n14=d*F+e*O+f*T+g*P;this.n21=j*I+k*B+m*w+o*h;this.n22=j*y+k*M+m*W+o*R;this.n23=j*G+k*L+m*S+o*J;this.n24=j*F+k*O+m*T+o*P;this.n31=n*I+t*B+p*w+u*h;this.n32=n*y+t*M+p*W+u*R;this.n33=n*G+t*L+p*S+u*J;this.n34=n*F+t*O+p*T+u*P;this.n41=v*I+z*B+C*w+A*h;this.n42=v*y+z*M+C*W+A*R;this.n43=v*G+z*L+C*S+A*J;this.n44=v*F+z*O+C*T+A*P;return this},multiplyToArray:function(b, +c,d){this.multiply(b,c);d[0]=this.n11;d[1]=this.n21;d[2]=this.n31;d[3]=this.n41;d[4]=this.n12;d[5]=this.n22;d[6]=this.n32;d[7]=this.n42;d[8]=this.n13;d[9]=this.n23;d[10]=this.n33;d[11]=this.n43;d[12]=this.n14;d[13]=this.n24;d[14]=this.n34;d[15]=this.n44;return this},multiplySelf:function(b){this.multiply(this,b);return this},multiplyScalar:function(b){this.n11*=b;this.n12*=b;this.n13*=b;this.n14*=b;this.n21*=b;this.n22*=b;this.n23*=b;this.n24*=b;this.n31*=b;this.n32*=b;this.n33*=b;this.n34*=b;this.n41*= +b;this.n42*=b;this.n43*=b;this.n44*=b;return this},determinant:function(){var b=this.n11,c=this.n12,d=this.n13,e=this.n14,f=this.n21,g=this.n22,j=this.n23,k=this.n24,m=this.n31,o=this.n32,n=this.n33,t=this.n34,p=this.n41,u=this.n42,v=this.n43,z=this.n44;return e*j*o*p-d*k*o*p-e*g*n*p+c*k*n*p+d*g*t*p-c*j*t*p-e*j*m*u+d*k*m*u+e*f*n*u-b*k*n*u-d*f*t*u+b*j*t*u+e*g*m*v-c*k*m*v-e*f*o*v+b*k*o*v+c*f*t*v-b*g*t*v-d*g*m*z+c*j*m*z+d*f*o*z-b*j*o*z-c*f*n*z+b*g*n*z},transpose:function(){var b;b=this.n21;this.n21= +this.n12;this.n12=b;b=this.n31;this.n31=this.n13;this.n13=b;b=this.n32;this.n32=this.n23;this.n23=b;b=this.n41;this.n41=this.n14;this.n14=b;b=this.n42;this.n42=this.n24;this.n24=b;b=this.n43;this.n43=this.n34;this.n43=b;return this},clone:function(){var b=new THREE.Matrix4;b.n11=this.n11;b.n12=this.n12;b.n13=this.n13;b.n14=this.n14;b.n21=this.n21;b.n22=this.n22;b.n23=this.n23;b.n24=this.n24;b.n31=this.n31;b.n32=this.n32;b.n33=this.n33;b.n34=this.n34;b.n41=this.n41;b.n42=this.n42;b.n43=this.n43;b.n44= +this.n44;return b},flatten:function(){this.flat[0]=this.n11;this.flat[1]=this.n21;this.flat[2]=this.n31;this.flat[3]=this.n41;this.flat[4]=this.n12;this.flat[5]=this.n22;this.flat[6]=this.n32;this.flat[7]=this.n42;this.flat[8]=this.n13;this.flat[9]=this.n23;this.flat[10]=this.n33;this.flat[11]=this.n43;this.flat[12]=this.n14;this.flat[13]=this.n24;this.flat[14]=this.n34;this.flat[15]=this.n44;return this.flat},flattenToArray:function(b){b[0]=this.n11;b[1]=this.n21;b[2]=this.n31;b[3]=this.n41;b[4]= +this.n12;b[5]=this.n22;b[6]=this.n32;b[7]=this.n42;b[8]=this.n13;b[9]=this.n23;b[10]=this.n33;b[11]=this.n43;b[12]=this.n14;b[13]=this.n24;b[14]=this.n34;b[15]=this.n44;return b},flattenToArrayOffset:function(b,c){b[c]=this.n11;b[c+1]=this.n21;b[c+2]=this.n31;b[c+3]=this.n41;b[c+4]=this.n12;b[c+5]=this.n22;b[c+6]=this.n32;b[c+7]=this.n42;b[c+8]=this.n13;b[c+9]=this.n23;b[c+10]=this.n33;b[c+11]=this.n43;b[c+12]=this.n14;b[c+13]=this.n24;b[c+14]=this.n34;b[c+15]=this.n44;return b},setTranslation:function(b, +c,d){this.set(1,0,0,b,0,1,0,c,0,0,1,d,0,0,0,1);return this},setScale:function(b,c,d){this.set(b,0,0,0,0,c,0,0,0,0,d,0,0,0,0,1);return this},setRotationX:function(b){var c=Math.cos(b),b=Math.sin(b);this.set(1,0,0,0,0,c,-b,0,0,b,c,0,0,0,0,1);return this},setRotationY:function(b){var c=Math.cos(b),b=Math.sin(b);this.set(c,0,b,0,0,1,0,0,-b,0,c,0,0,0,0,1);return this},setRotationZ:function(b){var c=Math.cos(b),b=Math.sin(b);this.set(c,-b,0,0,b,c,0,0,0,0,1,0,0,0,0,1);return this},setRotationAxis:function(b, +c){var d=Math.cos(c),e=Math.sin(c),f=1-d,g=b.x,j=b.y,k=b.z,m=f*g,o=f*j;this.set(m*g+d,m*j-e*k,m*k+e*j,0,m*j+e*k,o*j+d,o*k-e*g,0,m*k-e*j,o*k+e*g,f*k*k+d,0,0,0,0,1);return this},setPosition:function(b){this.n14=b.x;this.n24=b.y;this.n34=b.z;return this},getPosition:function(){if(!this.position)this.position=new THREE.Vector3;this.position.set(this.n14,this.n24,this.n34);return this.position},getColumnX:function(){if(!this.columnX)this.columnX=new THREE.Vector3;this.columnX.set(this.n11,this.n21,this.n31); +return this.columnX},getColumnY:function(){if(!this.columnY)this.columnY=new THREE.Vector3;this.columnY.set(this.n12,this.n22,this.n32);return this.columnY},getColumnZ:function(){if(!this.columnZ)this.columnZ=new THREE.Vector3;this.columnZ.set(this.n13,this.n23,this.n33);return this.columnZ},setRotationFromEuler:function(b,c){var d=b.x,e=b.y,f=b.z,g=Math.cos(d),d=Math.sin(d),j=Math.cos(e),e=Math.sin(e),k=Math.cos(f),f=Math.sin(f);switch(c){case "YXZ":var m=j*k,o=j*f,n=e*k,t=e*f;this.n11=m+t*d;this.n12= +n*d-o;this.n13=g*e;this.n21=g*f;this.n22=g*k;this.n23=-d;this.n31=o*d-n;this.n32=t+m*d;this.n33=g*j;break;case "ZXY":m=j*k;o=j*f;n=e*k;t=e*f;this.n11=m-t*d;this.n12=-g*f;this.n13=n+o*d;this.n21=o+n*d;this.n22=g*k;this.n23=t-m*d;this.n31=-g*e;this.n32=d;this.n33=g*j;break;case "ZYX":m=g*k;o=g*f;n=d*k;t=d*f;this.n11=j*k;this.n12=n*e-o;this.n13=m*e+t;this.n21=j*f;this.n22=t*e+m;this.n23=o*e-n;this.n31=-e;this.n32=d*j;this.n33=g*j;break;case "YZX":m=g*j;o=g*e;n=d*j;t=d*e;this.n11=j*k;this.n12=t-m*f;this.n13= +n*f+o;this.n21=f;this.n22=g*k;this.n23=-d*k;this.n31=-e*k;this.n32=o*f+n;this.n33=m-t*f;break;case "XZY":m=g*j;o=g*e;n=d*j;t=d*e;this.n11=j*k;this.n12=-f;this.n13=e*k;this.n21=m*f+t;this.n22=g*k;this.n23=o*f-n;this.n31=n*f-o;this.n32=d*k;this.n33=t*f+m;break;default:m=g*k,o=g*f,n=d*k,t=d*f,this.n11=j*k,this.n12=-j*f,this.n13=e,this.n21=o+n*e,this.n22=m-t*e,this.n23=-d*j,this.n31=t-m*e,this.n32=n+o*e,this.n33=g*j}return this},setRotationFromQuaternion:function(b){var c=b.x,d=b.y,e=b.z,f=b.w,g=c+c, +j=d+d,k=e+e,b=c*g,m=c*j;c*=k;var o=d*j;d*=k;e*=k;g*=f;j*=f;f*=k;this.n11=1-(o+e);this.n12=m-f;this.n13=c+j;this.n21=m+f;this.n22=1-(b+e);this.n23=d-g;this.n31=c-j;this.n32=d+g;this.n33=1-(b+o);return this},scale:function(b){var c=b.x,d=b.y,b=b.z;this.n11*=c;this.n12*=d;this.n13*=b;this.n21*=c;this.n22*=d;this.n23*=b;this.n31*=c;this.n32*=d;this.n33*=b;this.n41*=c;this.n42*=d;this.n43*=b;return this},extractPosition:function(b){this.n14=b.n14;this.n24=b.n24;this.n34=b.n34},extractRotation:function(b, +c){var d=1/c.x,e=1/c.y,f=1/c.z;this.n11=b.n11*d;this.n21=b.n21*d;this.n31=b.n31*d;this.n12=b.n12*e;this.n22=b.n22*e;this.n32=b.n32*e;this.n13=b.n13*f;this.n23=b.n23*f;this.n33=b.n33*f}}; +THREE.Matrix4.makeInvert=function(b,c){var d=b.n11,e=b.n12,f=b.n13,g=b.n14,j=b.n21,k=b.n22,m=b.n23,o=b.n24,n=b.n31,t=b.n32,p=b.n33,u=b.n34,v=b.n41,z=b.n42,C=b.n43,A=b.n44;c===void 0&&(c=new THREE.Matrix4);c.n11=m*u*z-o*p*z+o*t*C-k*u*C-m*t*A+k*p*A;c.n12=g*p*z-f*u*z-g*t*C+e*u*C+f*t*A-e*p*A;c.n13=f*o*z-g*m*z+g*k*C-e*o*C-f*k*A+e*m*A;c.n14=g*m*t-f*o*t-g*k*p+e*o*p+f*k*u-e*m*u;c.n21=o*p*v-m*u*v-o*n*C+j*u*C+m*n*A-j*p*A;c.n22=f*u*v-g*p*v+g*n*C-d*u*C-f*n*A+d*p*A;c.n23=g*m*v-f*o*v-g*j*C+d*o*C+f*j*A-d*m*A;c.n24= +f*o*n-g*m*n+g*j*p-d*o*p-f*j*u+d*m*u;c.n31=k*u*v-o*t*v+o*n*z-j*u*z-k*n*A+j*t*A;c.n32=g*t*v-e*u*v-g*n*z+d*u*z+e*n*A-d*t*A;c.n33=f*o*v-g*k*v+g*j*z-d*o*z-e*j*A+d*k*A;c.n34=g*k*n-e*o*n-g*j*t+d*o*t+e*j*u-d*k*u;c.n41=m*t*v-k*p*v-m*n*z+j*p*z+k*n*C-j*t*C;c.n42=e*p*v-f*t*v+f*n*z-d*p*z-e*n*C+d*t*C;c.n43=f*k*v-e*m*v-f*j*z+d*m*z+e*j*C-d*k*C;c.n44=e*m*n-f*k*n+f*j*t-d*m*t-e*j*p+d*k*p;c.multiplyScalar(1/b.determinant());return c}; +THREE.Matrix4.makeInvert3x3=function(b){var c=b.m33,d=c.m,e=b.n33*b.n22-b.n32*b.n23,f=-b.n33*b.n21+b.n31*b.n23,g=b.n32*b.n21-b.n31*b.n22,j=-b.n33*b.n12+b.n32*b.n13,k=b.n33*b.n11-b.n31*b.n13,m=-b.n32*b.n11+b.n31*b.n12,o=b.n23*b.n12-b.n22*b.n13,n=-b.n23*b.n11+b.n21*b.n13,t=b.n22*b.n11-b.n21*b.n12,b=b.n11*e+b.n21*j+b.n31*o;b==0&&console.error("THREE.Matrix4.makeInvert3x3: Matrix not invertible.");b=1/b;d[0]=b*e;d[1]=b*f;d[2]=b*g;d[3]=b*j;d[4]=b*k;d[5]=b*m;d[6]=b*o;d[7]=b*n;d[8]=b*t;return c}; +THREE.Matrix4.makeFrustum=function(b,c,d,e,f,g){var j;j=new THREE.Matrix4;j.n11=2*f/(c-b);j.n12=0;j.n13=(c+b)/(c-b);j.n14=0;j.n21=0;j.n22=2*f/(e-d);j.n23=(e+d)/(e-d);j.n24=0;j.n31=0;j.n32=0;j.n33=-(g+f)/(g-f);j.n34=-2*g*f/(g-f);j.n41=0;j.n42=0;j.n43=-1;j.n44=0;return j};THREE.Matrix4.makePerspective=function(b,c,d,e){var f,b=d*Math.tan(b*Math.PI/360);f=-b;return THREE.Matrix4.makeFrustum(f*c,b*c,f,b,d,e)}; +THREE.Matrix4.makeOrtho=function(b,c,d,e,f,g){var j,k,m,o;j=new THREE.Matrix4;k=c-b;m=d-e;o=g-f;j.n11=2/k;j.n12=0;j.n13=0;j.n14=-((c+b)/k);j.n21=0;j.n22=2/m;j.n23=0;j.n24=-((d+e)/m);j.n31=0;j.n32=0;j.n33=-2/o;j.n34=-((g+f)/o);j.n41=0;j.n42=0;j.n43=0;j.n44=1;return j};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3; +THREE.Object3D=function(){this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=this.dynamic=!1;this.renderDepth=null;this.rotationAutoUpdate=!0;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate=!0;this.quaternion=new THREE.Quaternion; +this.useQuaternion=!1;this.boundRadius=0;this.boundRadiusScale=1;this.visible=!0;this._vector=new THREE.Vector3;this.name=""}; +THREE.Object3D.prototype={translate:function(b,c){this.matrix.rotateAxis(c);this.position.addSelf(c.multiplyScalar(b))},translateX:function(b){this.translate(b,this._vector.set(1,0,0))},translateY:function(b){this.translate(b,this._vector.set(0,1,0))},translateZ:function(b){this.translate(b,this._vector.set(0,0,1))},lookAt:function(b){this.matrix.lookAt(b,this.position,this.up);this.rotationAutoUpdate&&this.rotation.setRotationFromMatrix(this.matrix)},addChild:function(b){if(this.children.indexOf(b)=== +-1){b.parent!==void 0&&b.parent.removeChild(b);b.parent=this;this.children.push(b);for(var c=this;c.parent!==void 0;)c=c.parent;c!==void 0&&c instanceof THREE.Scene&&c.addChildRecurse(b)}},removeChild:function(b){var c=this.children.indexOf(b);if(c!==-1)b.parent=void 0,this.children.splice(c,1)},getChildByName:function(b,c){var d,e,f;d=0;for(e=this.children.length;d=1)return d.w=b.w,d.x=b.x,d.y=b.y,d.z=b.z,d;var g=Math.acos(f),j=Math.sqrt(1-f*f);if(Math.abs(j)<0.001)return d.w=0.5*(b.w+c.w),d.x=0.5*(b.x+c.x),d.y=0.5*(b.y+c.y),d.z=0.5*(b.z+c.z),d;f=Math.sin((1-e)*g)/j;e=Math.sin(e*g)/j;d.w=b.w*f+c.w*e;d.x=b.x*f+c.x*e;d.y=b.y*f+c.y*e;d.z=b.z*f+c.z*e;return d};THREE.Vertex=function(b){this.position=b||new THREE.Vector3}; +THREE.Face3=function(b,c,d,e,f,g){this.a=b;this.b=c;this.c=d;this.normal=e instanceof THREE.Vector3?e:new THREE.Vector3;this.vertexNormals=e instanceof Array?e:[];this.color=f instanceof THREE.Color?f:new THREE.Color;this.vertexColors=f instanceof Array?f:[];this.vertexTangents=[];this.materials=g instanceof Array?g:[g];this.centroid=new THREE.Vector3}; +THREE.Face4=function(b,c,d,e,f,g,j){this.a=b;this.b=c;this.c=d;this.d=e;this.normal=f instanceof THREE.Vector3?f:new THREE.Vector3;this.vertexNormals=f instanceof Array?f:[];this.color=g instanceof THREE.Color?g:new THREE.Color;this.vertexColors=g instanceof Array?g:[];this.vertexTangents=[];this.materials=j instanceof Array?j:[j];this.centroid=new THREE.Vector3};THREE.UV=function(b,c){this.set(b||0,c||0)}; +THREE.UV.prototype={set:function(b,c){this.u=b;this.v=c;return this},copy:function(b){this.set(b.u,b.v);return this}};THREE.Geometry=function(){this.id="Geometry"+THREE.GeometryIdCounter++;this.vertices=[];this.colors=[];this.faces=[];this.edges=[];this.faceUvs=[[]];this.faceVertexUvs=[[]];this.morphTargets=[];this.morphColors=[];this.skinWeights=[];this.skinIndices=[];this.boundingSphere=this.boundingBox=null;this.hasTangents=!1}; +THREE.Geometry.prototype={computeCentroids:function(){var b,c,d;b=0;for(c=this.faces.length;b0){this.boundingBox={x:[this.vertices[0].position.x,this.vertices[0].position.x],y:[this.vertices[0].position.y,this.vertices[0].position.y],z:[this.vertices[0].position.z,this.vertices[0].position.z]};for(var c=1,d=this.vertices.length;cthis.boundingBox.x[1])this.boundingBox.x[1]=b.position.x;if(b.position.ythis.boundingBox.y[1])this.boundingBox.y[1]=b.position.y;if(b.position.zthis.boundingBox.z[1])this.boundingBox.z[1]=b.position.z}}},computeBoundingSphere:function(){for(var b=0,c=0,d=this.vertices.length;cthis.points.length-2?g:g+1;d[3]=g>this.points.length-3?g:g+2;o=this.points[d[0]];n=this.points[d[1]]; +t=this.points[d[2]];p=this.points[d[3]];k=j*j;m=j*k;e.x=c(o.x,n.x,t.x,p.x,j,k,m);e.y=c(o.y,n.y,t.y,p.y,j,k,m);e.z=c(o.z,n.z,t.z,p.z,j,k,m);return e};this.getControlPointsArray=function(){var b,d,c=this.points.length,e=[];for(b=0;b1){b=d.matrixWorldInverse;b=-(b.n31*this.position.x+b.n32*this.position.y+b.n33*this.position.z+b.n34);this.LODs[0].object3D.visible=!0;for(var e=1;e=this.LODs[e].visibleAtDistance)this.LODs[e-1].object3D.visible=!1, +this.LODs[e].object3D.visible=!0;else break;for(;et&&(d=n,n=t,t=d):nu&&(d=p,p=u,u=d):p=0&&g>=0&&j>=0&&k>=0?!0:f<0&&g<0||j<0&&k<0?!1:(f<0?c=Math.max(c,f/(f-g)):g<0&&(e=Math.min(e,f/(f-g))),j<0?c=Math.max(c,j/(j-k)):k<0&&(e=Math.min(e,j/(j-k))),eG&&j.positionScreen.z0&&F.z<1))H=y[I]=y[I]||new THREE.RenderableParticle,I++,A=H,A.x=F.x/F.w,A.y=F.y/F.w,A.z=F.z,A.rotation=D.rotation.z,A.scale.x=D.scale.x*Math.abs(A.x-(F.x+f.projectionMatrix.n11)/(F.w+f.projectionMatrix.n14)),A.scale.y=D.scale.y*Math.abs(A.y-(F.y+ +f.projectionMatrix.n22)/(F.w+f.projectionMatrix.n24)),A.materials=D.materials,h.push(A);g&&h.sort(c);return h}}; +THREE.DOMRenderer=function(){THREE.Renderer.call(this);var b=null,c=new THREE.Projector,d,e,f,g;this.domElement=document.createElement("div");this.setSize=function(b,c){d=b;e=c;f=d/2;g=e/2};this.render=function(d,e){var m,o,n,t,p,u,v,z;b=c.projectScene(d,e);m=0;for(o=b.length;m>1,t=o.height>> +1,g=h.scale.x*p,m=h.scale.y*u,j=g*aa,k=m*t,na.set(b.x-j,b.y-k,b.x+j,b.y+k),Da.instersects(na)&&(v.save(),v.translate(b.x,b.y),v.rotate(-h.rotation),v.scale(g,-m),v.translate(-aa,-t),v.drawImage(o,0,0),v.restore())}else g instanceof THREE.ParticleCanvasMaterial&&(j=h.scale.x*p,k=h.scale.y*u,na.set(b.x-j,b.y-k,b.x+j,b.y+k),Da.instersects(na)&&(e(g.color),f(g.color),v.save(),v.translate(b.x,b.y),v.rotate(-h.rotation),v.scale(j,k),g.program(v),v.restore()))}function A(b,h,f,g){c(g.opacity);d(g.blending); +v.beginPath();v.moveTo(b.positionScreen.x,b.positionScreen.y);v.lineTo(h.positionScreen.x,h.positionScreen.y);v.closePath();if(g instanceof THREE.LineBasicMaterial){b=g.linewidth;if(F!=b)v.lineWidth=F=b;b=g.linecap;if(B!=b)v.lineCap=B=b;b=g.linejoin;if(M!=b)v.lineJoin=M=b;e(g.color);v.stroke();na.inflate(g.linewidth*2)}}function z(b,e,f,k,m,o,n,p,u){j.data.vertices+=3;j.data.faces++;c(p.opacity);d(p.blending);h=b.positionScreen.x;R=b.positionScreen.y;J=e.positionScreen.x;P=e.positionScreen.y;Q=f.positionScreen.x; +N=f.positionScreen.y;y(h,R,J,P,Q,N);if(p instanceof THREE.MeshBasicMaterial)if(p.map)p.map.mapping instanceof THREE.UVMapping&&(ta=n.uvs[0],K(h,R,J,P,Q,N,p.map.image,ta[k].u,ta[k].v,ta[m].u,ta[m].v,ta[o].u,ta[o].v));else if(p.envMap){if(p.envMap.mapping instanceof THREE.SphericalReflectionMapping)b=g.matrixWorldInverse,ja.copy(n.vertexNormalsWorld[0]),$a=(ja.x*b.n11+ja.y*b.n12+ja.z*b.n13)*0.5+0.5,ab=-(ja.x*b.n21+ja.y*b.n22+ja.z*b.n23)*0.5+0.5,ja.copy(n.vertexNormalsWorld[1]),bb=(ja.x*b.n11+ja.y*b.n12+ +ja.z*b.n13)*0.5+0.5,cb=-(ja.x*b.n21+ja.y*b.n22+ja.z*b.n23)*0.5+0.5,ja.copy(n.vertexNormalsWorld[2]),db=(ja.x*b.n11+ja.y*b.n12+ja.z*b.n13)*0.5+0.5,eb=-(ja.x*b.n21+ja.y*b.n22+ja.z*b.n23)*0.5+0.5,K(h,R,J,P,Q,N,p.envMap.image,$a,ab,bb,cb,db,eb)}else p.wireframe?G(p.color,p.wireframeLinewidth,p.wireframeLinecap,p.wireframeLinejoin):Aa(p.color);else if(p instanceof THREE.MeshLambertMaterial)p.map&&!p.wireframe&&(p.map.mapping instanceof THREE.UVMapping&&(ta=n.uvs[0],K(h,R,J,P,Q,N,p.map.image,ta[k].u,ta[k].v, +ta[m].u,ta[m].v,ta[o].u,ta[o].v)),d(THREE.SubtractiveBlending)),Sa?!p.wireframe&&p.shading==THREE.SmoothShading&&n.vertexNormalsWorld.length==3?(H.r=$.r=ca.r=qa.r,H.g=$.g=ca.g=qa.g,H.b=$.b=ca.b=qa.b,t(u,n.v1.positionWorld,n.vertexNormalsWorld[0],H),t(u,n.v2.positionWorld,n.vertexNormalsWorld[1],$),t(u,n.v3.positionWorld,n.vertexNormalsWorld[2],ca),aa.r=($.r+ca.r)*0.5,aa.g=($.g+ca.g)*0.5,aa.b=($.b+ca.b)*0.5,pa=Qa(H,$,ca,aa),K(h,R,J,P,Q,N,pa,0,0,1,0,0,1)):(ua.r=qa.r,ua.g=qa.g,ua.b=qa.b,t(u,n.centroidWorld, +n.normalWorld,ua),D.r=Math.max(0,Math.min(p.color.r*ua.r,1)),D.g=Math.max(0,Math.min(p.color.g*ua.g,1)),D.b=Math.max(0,Math.min(p.color.b*ua.b,1)),D.updateHex(),p.wireframe?G(D,p.wireframeLinewidth,p.wireframeLinecap,p.wireframeLinejoin):Aa(D)):p.wireframe?G(p.color,p.wireframeLinewidth,p.wireframeLinecap,p.wireframeLinejoin):Aa(p.color);else if(p instanceof THREE.MeshDepthMaterial)oa=g.near,va=g.far,H.r=H.g=H.b=1-Ea(b.positionScreen.z,oa,va),$.r=$.g=$.b=1-Ea(e.positionScreen.z,oa,va),ca.r=ca.g=ca.b= +1-Ea(f.positionScreen.z,oa,va),aa.r=($.r+ca.r)*0.5,aa.g=($.g+ca.g)*0.5,aa.b=($.b+ca.b)*0.5,pa=Qa(H,$,ca,aa),K(h,R,J,P,Q,N,pa,0,0,1,0,0,1);else if(p instanceof THREE.MeshNormalMaterial)D.r=Ka(n.normalWorld.x),D.g=Ka(n.normalWorld.y),D.b=Ka(n.normalWorld.z),D.updateHex(),p.wireframe?G(D,p.wireframeLinewidth,p.wireframeLinecap,p.wireframeLinejoin):Aa(D)}function C(b,e,f,k,m,o,n,p,u){j.data.vertices+=4;j.data.faces++;c(p.opacity);d(p.blending);if(p.map||p.envMap)z(b,e,k,0,1,3,n,p,u),z(m,f,o,1,2,3,n,p, +u);else if(h=b.positionScreen.x,R=b.positionScreen.y,J=e.positionScreen.x,P=e.positionScreen.y,Q=f.positionScreen.x,N=f.positionScreen.y,Y=k.positionScreen.x,V=k.positionScreen.y,Z=m.positionScreen.x,U=m.positionScreen.y,ea=o.positionScreen.x,ia=o.positionScreen.y,p instanceof THREE.MeshBasicMaterial)I(h,R,J,P,Q,N,Y,V),p.wireframe?G(p.color,p.wireframeLinewidth,p.wireframeLinecap,p.wireframeLinejoin):Aa(p.color);else if(p instanceof THREE.MeshLambertMaterial)Sa?!p.wireframe&&p.shading==THREE.SmoothShading&& +n.vertexNormalsWorld.length==4?(H.r=$.r=ca.r=aa.r=qa.r,H.g=$.g=ca.g=aa.g=qa.g,H.b=$.b=ca.b=aa.b=qa.b,t(u,n.v1.positionWorld,n.vertexNormalsWorld[0],H),t(u,n.v2.positionWorld,n.vertexNormalsWorld[1],$),t(u,n.v4.positionWorld,n.vertexNormalsWorld[3],ca),t(u,n.v3.positionWorld,n.vertexNormalsWorld[2],aa),pa=Qa(H,$,ca,aa),y(h,R,J,P,Y,V),K(h,R,J,P,Y,V,pa,0,0,1,0,0,1),y(Z,U,Q,N,ea,ia),K(Z,U,Q,N,ea,ia,pa,1,0,1,1,0,1)):(ua.r=qa.r,ua.g=qa.g,ua.b=qa.b,t(u,n.centroidWorld,n.normalWorld,ua),D.r=Math.max(0,Math.min(p.color.r* +ua.r,1)),D.g=Math.max(0,Math.min(p.color.g*ua.g,1)),D.b=Math.max(0,Math.min(p.color.b*ua.b,1)),D.updateHex(),I(h,R,J,P,Q,N,Y,V),p.wireframe?G(D,p.wireframeLinewidth,p.wireframeLinecap,p.wireframeLinejoin):Aa(D)):(I(h,R,J,P,Q,N,Y,V),p.wireframe?G(p.color,p.wireframeLinewidth,p.wireframeLinecap,p.wireframeLinejoin):Aa(p.color));else if(p instanceof THREE.MeshNormalMaterial)D.r=Ka(n.normalWorld.x),D.g=Ka(n.normalWorld.y),D.b=Ka(n.normalWorld.z),D.updateHex(),I(h,R,J,P,Q,N,Y,V),p.wireframe?G(D,p.wireframeLinewidth, +p.wireframeLinecap,p.wireframeLinejoin):Aa(D);else if(p instanceof THREE.MeshDepthMaterial)oa=g.near,va=g.far,H.r=H.g=H.b=1-Ea(b.positionScreen.z,oa,va),$.r=$.g=$.b=1-Ea(e.positionScreen.z,oa,va),ca.r=ca.g=ca.b=1-Ea(k.positionScreen.z,oa,va),aa.r=aa.g=aa.b=1-Ea(f.positionScreen.z,oa,va),pa=Qa(H,$,ca,aa),y(h,R,J,P,Y,V),K(h,R,J,P,Y,V,pa,0,0,1,0,0,1),y(Z,U,Q,N,ea,ia),K(Z,U,Q,N,ea,ia,pa,1,0,1,1,0,1)}function y(b,d,c,e,h,f){v.beginPath();v.moveTo(b,d);v.lineTo(c,e);v.lineTo(h,f);v.lineTo(b,d);v.closePath()} +function I(b,d,c,e,h,f,g,j){v.beginPath();v.moveTo(b,d);v.lineTo(c,e);v.lineTo(h,f);v.lineTo(g,j);v.lineTo(b,d);v.closePath()}function G(b,d,c,h){if(F!=d)v.lineWidth=F=d;if(B!=c)v.lineCap=B=c;if(M!=h)v.lineJoin=M=h;e(b);v.stroke();na.inflate(d*2)}function Aa(b){f(b);v.fill()}function K(b,d,c,e,h,f,g,j,k,m,o,aa,p){var n,t;n=g.width-1;t=g.height-1;j*=n;k*=t;m*=n;o*=t;aa*=n;p*=t;c-=b;e-=d;h-=b;f-=d;m-=j;o-=k;aa-=j;p-=k;n=m*p-aa*o;n!=0&&(t=1/n,n=(p*c-o*h)*t,o=(p*e-o*f)*t,c=(m*h-aa*c)*t,e=(m*f-aa*e)*t, +b=b-n*j-c*k,d=d-o*j-e*k,v.save(),v.transform(n,o,c,e,b,d),v.clip(),v.drawImage(g,0,0),v.restore())}function Qa(b,d,c,e){var h=~~(b.r*255),f=~~(b.g*255),b=~~(b.b*255),g=~~(d.r*255),j=~~(d.g*255),d=~~(d.b*255),k=~~(c.r*255),m=~~(c.g*255),c=~~(c.b*255),o=~~(e.r*255),aa=~~(e.g*255),e=~~(e.b*255);xa[0]=h<0?0:h>255?255:h;xa[1]=f<0?0:f>255?255:f;xa[2]=b<0?0:b>255?255:b;xa[4]=g<0?0:g>255?255:g;xa[5]=j<0?0:j>255?255:j;xa[6]=d<0?0:d>255?255:d;xa[8]=k<0?0:k>255?255:k;xa[9]=m<0?0:m>255?255:m;xa[10]=c<0?0:c>255? +255:c;xa[12]=o<0?0:o>255?255:o;xa[13]=aa<0?0:aa>255?255:aa;xa[14]=e<0?0:e>255?255:e;Ma.putImageData(Ta,0,0);Pa.drawImage(La,0,0);return E}function Ea(b,d,c){b=(b-d)/(c-d);return b*b*(3-2*b)}function Ka(b){b=(b+1)*0.5;return b<0?0:b>1?1:b}function Ba(b,d){var c=d.x-b.x,e=d.y-b.y,h=1/Math.sqrt(c*c+e*e);c*=h;e*=h;d.x+=c;d.y+=e;b.x-=c;b.y-=e}var Ra,hb,X,da,fa,ga,ha,la;this.autoClear?this.clear():v.setTransform(1,0,0,-1,p,u);j.data.vertices=0;j.data.faces=0;k=m.projectScene(b,g,this.sortElements);(Sa= +b.lights.length>0)&&o(b);Ra=0;for(hb=k.length;Ra0&&(c.r+=f.color.r*g,c.g+=f.color.g*g,c.b+=f.color.b*g)):f instanceof THREE.PointLight&&(W.sub(f.position,d.centroidWorld),W.normalize(),g=d.normalWorld.dot(W)*f.intensity,g>0&&(c.r+=f.color.r*g,c.g+=f.color.g*g,c.b+=f.color.b*g))}function c(d,c,k,m,p,n){j.data.vertices+=3;j.data.faces++;h=e(R++);h.setAttribute("d", +"M "+d.positionScreen.x+" "+d.positionScreen.y+" L "+c.positionScreen.x+" "+c.positionScreen.y+" L "+k.positionScreen.x+","+k.positionScreen.y+"z");p instanceof THREE.MeshBasicMaterial?F.hex=p.color.hex:p instanceof THREE.MeshLambertMaterial?G?(B.r=M.r,B.g=M.g,B.b=M.b,b(n,m,B),F.r=Math.max(0,Math.min(p.color.r*B.r,1)),F.g=Math.max(0,Math.min(p.color.g*B.g,1)),F.b=Math.max(0,Math.min(p.color.b*B.b,1)),F.updateHex()):F.hex=p.color.hex:p instanceof THREE.MeshDepthMaterial?(w=1-p.__2near/(p.__farPlusNear- +m.z*p.__farMinusNear),F.setRGB(w,w,w)):p instanceof THREE.MeshNormalMaterial&&F.setRGB(f(m.normalWorld.x),f(m.normalWorld.y),f(m.normalWorld.z));p.wireframe?h.setAttribute("style","fill: none; stroke: #"+g(F.hex.toString(16))+"; stroke-width: "+p.wireframeLinewidth+"; stroke-opacity: "+p.opacity+"; stroke-linecap: "+p.wireframeLinecap+"; stroke-linejoin: "+p.wireframeLinejoin):h.setAttribute("style","fill: #"+g(F.hex.toString(16))+"; fill-opacity: "+p.opacity);o.appendChild(h)}function d(d,c,k,m, +p,n,t){j.data.vertices+=4;j.data.faces++;h=e(R++);h.setAttribute("d","M "+d.positionScreen.x+" "+d.positionScreen.y+" L "+c.positionScreen.x+" "+c.positionScreen.y+" L "+k.positionScreen.x+","+k.positionScreen.y+" L "+m.positionScreen.x+","+m.positionScreen.y+"z");n instanceof THREE.MeshBasicMaterial?F.hex=n.color.hex:n instanceof THREE.MeshLambertMaterial?G?(B.r=M.r,B.g=M.g,B.b=M.b,b(t,p,B),F.r=Math.max(0,Math.min(n.color.r*B.r,1)),F.g=Math.max(0,Math.min(n.color.g*B.g,1)),F.b=Math.max(0,Math.min(n.color.b* +B.b,1)),F.updateHex()):F.hex=n.color.hex:n instanceof THREE.MeshDepthMaterial?(w=1-n.__2near/(n.__farPlusNear-p.z*n.__farMinusNear),F.setRGB(w,w,w)):n instanceof THREE.MeshNormalMaterial&&F.setRGB(f(p.normalWorld.x),f(p.normalWorld.y),f(p.normalWorld.z));n.wireframe?h.setAttribute("style","fill: none; stroke: #"+g(F.hex.toString(16))+"; stroke-width: "+n.wireframeLinewidth+"; stroke-opacity: "+n.opacity+"; stroke-linecap: "+n.wireframeLinecap+"; stroke-linejoin: "+n.wireframeLinejoin):h.setAttribute("style", +"fill: #"+g(F.hex.toString(16))+"; fill-opacity: "+n.opacity);o.appendChild(h)}function e(b){S[b]==null&&(S[b]=document.createElementNS("http://www.w3.org/2000/svg","path"),P==0&&S[b].setAttribute("shape-rendering","crispEdges"));return S[b]}function f(b){b=(b+1)*0.5;return b<0?0:b>1?1:b}function g(b){for(;b.length<6;)b="0"+b;return b}var j=this,k=null,m=new THREE.Projector,o=document.createElementNS("http://www.w3.org/2000/svg","svg"),n,t,p,u,v,z,C,A,I=new THREE.Rectangle,y=new THREE.Rectangle,G= +!1,F=new THREE.Color(16777215),B=new THREE.Color(16777215),M=new THREE.Color(0),L=new THREE.Color(0),O=new THREE.Color(0),w,W=new THREE.Vector3,S=[],T=[],h,R,J,P=1;this.domElement=o;this.sortElements=this.sortObjects=this.autoClear=!0;this.data={vertices:0,faces:0};this.setQuality=function(b){switch(b){case "high":P=1;break;case "low":P=0}};this.setSize=function(b,d){n=b;t=d;p=n/2;u=t/2;o.setAttribute("viewBox",-p+" "+-u+" "+n+" "+t);o.setAttribute("width",n);o.setAttribute("height",t);I.set(-p,-u, +p,u)};this.clear=function(){for(;o.childNodes.length>0;)o.removeChild(o.childNodes[0])};this.render=function(b,e){var f,n,t,F,B,w,D,H;this.autoClear&&this.clear();j.data.vertices=0;j.data.faces=0;k=m.projectScene(b,e,this.sortElements);J=R=0;if(G=b.lights.length>0){D=b.lights;M.setRGB(0,0,0);L.setRGB(0,0,0);O.setRGB(0,0,0);f=0;for(n=D.length;f 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#ifdef PHONG\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif", +lights_vertex:"if ( !enableLighting ) {\nvLightWeighting = vec3( 1.0 );\n} else {\nvLightWeighting = ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nfloat directionalLightWeighting = max( dot( transformedNormal, normalize( lDirection.xyz ) ), 0.0 );\nvLightWeighting += directionalLightColor[ i ] * directionalLightWeighting;\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat pointLightWeighting = max( dot( transformedNormal, lVector ), 0.0 );\nvLightWeighting += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef PHONG\nvPointLight[ i ] = vec4( lVector, lDistance );\n#endif\n}\n#endif\n}", +lights_pars_fragment:"#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;",lights_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\nvec4 mColor = vec4( diffuse, opacity );\nvec4 mSpecular = vec4( specular, opacity );\n#if MAX_POINT_LIGHTS > 0\nvec4 pointDiffuse = vec4( 0.0 );\nvec4 pointSpecular = vec4( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec3 pointVector = normalize( vPointLight[ i ].xyz );\nvec3 pointHalfVector = normalize( vPointLight[ i ].xyz + vViewPosition );\nfloat pointDistance = vPointLight[ i ].w;\nfloat pointDotNormalHalf = dot( normal, pointHalfVector );\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\nfloat pointSpecularWeight = 0.0;\nif ( pointDotNormalHalf >= 0.0 )\npointSpecularWeight = pow( pointDotNormalHalf, shininess );\npointDiffuse += mColor * pointDiffuseWeight * pointDistance;\npointSpecular += mSpecular * pointSpecularWeight * pointDistance;\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec4 dirDiffuse = vec4( 0.0 );\nvec4 dirSpecular = vec4( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nvec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );\nfloat dirDotNormalHalf = dot( normal, dirHalfVector );\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\nfloat dirSpecularWeight = 0.0;\nif ( dirDotNormalHalf >= 0.0 )\ndirSpecularWeight = pow( dirDotNormalHalf, shininess );\ndirDiffuse += mColor * dirDiffuseWeight;\ndirSpecular += mSpecular * dirSpecularWeight;\n}\n#endif\nvec4 totalLight = vec4( ambient, opacity );\n#if MAX_DIR_LIGHTS > 0\ntotalLight += dirDiffuse + dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalLight += pointDiffuse + pointSpecular;\n#endif\ngl_FragColor = gl_FragColor * totalLight;", +color_pars_fragment:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_fragment:"#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif",color_pars_vertex:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\nvColor = color;\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\n#endif",skinning_vertex:"#ifdef USE_SKINNING\ngl_Position = ( boneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;\ngl_Position += ( boneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;\ngl_Position = projectionMatrix * viewMatrix * objectMatrix * gl_Position;\n#endif", +morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\nuniform float morphTargetInfluences[ 8 ];\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0, 0.0, 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\nmorphed += position;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );\n#endif", +default_vertex:"#ifndef USE_MORPHTARGETS\n#ifndef USE_SKINNING\ngl_Position = projectionMatrix * mvPosition;\n#endif\n#endif"};THREE.UniformsUtils={merge:function(b){var c,d,e,f={};for(c=0;c=0)h.bindBuffer(h.ARRAY_BUFFER,g.__webglVertexBuffer),h.vertexAttribPointer(b.position, +3,h.FLOAT,!1,0,0);else{c=f.program.attributes;j.morphTargetBase!==-1?(h.bindBuffer(h.ARRAY_BUFFER,g.__webglMorphTargetsBuffers[j.morphTargetBase]),h.vertexAttribPointer(c.position,3,h.FLOAT,!1,0,0)):c.position>=0&&(h.bindBuffer(h.ARRAY_BUFFER,g.__webglVertexBuffer),h.vertexAttribPointer(c.position,3,h.FLOAT,!1,0,0));if(j.morphTargetForcedOrder.length)for(var e=0,m=j.morphTargetForcedOrder,o=j.morphTargetInfluences;ep&&(n=t,p=o[n]);h.bindBuffer(h.ARRAY_BUFFER,g.__webglMorphTargetsBuffers[n]);h.vertexAttribPointer(c["morphTarget"+e],3,h.FLOAT,!1,0,0);j.__webglMorphTargetInfluences[e]=p;m[n]=1;p=-1;e++}}f.program.uniforms.morphTargetInfluences!== +null&&h.uniform1fv(f.program.uniforms.morphTargetInfluences,j.__webglMorphTargetInfluences)}if(g.__webglCustomAttributes)for(k in g.__webglCustomAttributes)b[k]>=0&&(c=g.__webglCustomAttributes[k],h.bindBuffer(h.ARRAY_BUFFER,c.buffer),h.vertexAttribPointer(b[k],c.size,h.FLOAT,!1,0,0));b.color>=0&&(h.bindBuffer(h.ARRAY_BUFFER,g.__webglColorBuffer),h.vertexAttribPointer(b.color,3,h.FLOAT,!1,0,0));b.normal>=0&&(h.bindBuffer(h.ARRAY_BUFFER,g.__webglNormalBuffer),h.vertexAttribPointer(b.normal,3,h.FLOAT, +!1,0,0));b.tangent>=0&&(h.bindBuffer(h.ARRAY_BUFFER,g.__webglTangentBuffer),h.vertexAttribPointer(b.tangent,4,h.FLOAT,!1,0,0));b.uv>=0&&(g.__webglUVBuffer?(h.bindBuffer(h.ARRAY_BUFFER,g.__webglUVBuffer),h.vertexAttribPointer(b.uv,2,h.FLOAT,!1,0,0),h.enableVertexAttribArray(b.uv)):h.disableVertexAttribArray(b.uv));b.uv2>=0&&(g.__webglUV2Buffer?(h.bindBuffer(h.ARRAY_BUFFER,g.__webglUV2Buffer),h.vertexAttribPointer(b.uv2,2,h.FLOAT,!1,0,0),h.enableVertexAttribArray(b.uv2)):h.disableVertexAttribArray(b.uv2)); +f.skinning&&b.skinVertexA>=0&&b.skinVertexB>=0&&b.skinIndex>=0&&b.skinWeight>=0&&(h.bindBuffer(h.ARRAY_BUFFER,g.__webglSkinVertexABuffer),h.vertexAttribPointer(b.skinVertexA,4,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,g.__webglSkinVertexBBuffer),h.vertexAttribPointer(b.skinVertexB,4,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,g.__webglSkinIndicesBuffer),h.vertexAttribPointer(b.skinIndex,4,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,g.__webglSkinWeightsBuffer),h.vertexAttribPointer(b.skinWeight, +4,h.FLOAT,!1,0,0));j instanceof THREE.Mesh?(f.wireframe?(h.lineWidth(f.wireframeLinewidth),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,g.__webglLineBuffer),h.drawElements(h.LINES,g.__webglLineCount,h.UNSIGNED_SHORT,0)):(h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,g.__webglFaceBuffer),h.drawElements(h.TRIANGLES,g.__webglFaceCount,h.UNSIGNED_SHORT,0)),T.data.vertices+=g.__webglFaceCount,T.data.faces+=g.__webglFaceCount/3,T.data.drawCalls++):j instanceof THREE.Line?(j=j.type==THREE.LineStrip?h.LINE_STRIP:h.LINES,h.lineWidth(f.linewidth), +h.drawArrays(j,0,g.__webglLineCount),T.data.drawCalls++):j instanceof THREE.ParticleSystem?(h.drawArrays(h.POINTS,0,g.__webglParticleCount),T.data.drawCalls++):j instanceof THREE.Ribbon&&(h.drawArrays(h.TRIANGLE_STRIP,0,g.__webglVertexCount),T.data.drawCalls++)}}function f(b,d,c){if(!b.__webglVertexBuffer)b.__webglVertexBuffer=h.createBuffer();if(!b.__webglNormalBuffer)b.__webglNormalBuffer=h.createBuffer();b.hasPos&&(h.bindBuffer(h.ARRAY_BUFFER,b.__webglVertexBuffer),h.bufferData(h.ARRAY_BUFFER, +b.positionArray,h.DYNAMIC_DRAW),h.enableVertexAttribArray(d.attributes.position),h.vertexAttribPointer(d.attributes.position,3,h.FLOAT,!1,0,0));if(b.hasNormal){h.bindBuffer(h.ARRAY_BUFFER,b.__webglNormalBuffer);if(c==THREE.FlatShading){var e,f,g,j,k,m,o,p,n,t,u=b.count*3;for(t=0;t0&&A[0]<_viewportWidth&&A[1]>0&&A[1]<_viewportHeight){h.bindTexture(h.TEXTURE_2D,H.tempTexture); +h.copyTexImage2D(h.TEXTURE_2D,0,h.RGB,A[0]-8,A[1]-8,16,16,0);h.uniform1i(z.renderType,0);h.uniform2fv(z.scale,u);h.uniform3fv(z.screenPosition,v);h.disable(h.BLEND);h.enable(h.DEPTH_TEST);h.drawElements(h.TRIANGLES,6,h.UNSIGNED_SHORT,0);h.bindTexture(h.TEXTURE_2D,H.occlusionTexture);h.copyTexImage2D(h.TEXTURE_2D,0,h.RGBA,A[0]-8,A[1]-8,16,16,0);h.uniform1i(z.renderType,1);h.disable(h.DEPTH_TEST);h.bindTexture(h.TEXTURE_2D,H.tempTexture);h.drawElements(h.TRIANGLES,6,h.UNSIGNED_SHORT,0);c.positionScreen.x= +v[0];c.positionScreen.y=v[1];c.positionScreen.z=v[2];c.customUpdateCallback?c.customUpdateCallback(c):c.updateLensFlares();h.uniform1i(z.renderType,2);h.enable(h.BLEND);g=0;for(j=c.lensFlares.length;g0.001&&k.scale>0.001)v[0]=k.x,v[1]=k.y,v[2]=k.z,t=k.size*k.scale/_viewportHeight,u[0]=t*o,u[1]=t,h.uniform3fv(z.screenPosition,v),h.uniform2fv(z.scale,u),h.uniform1f(z.rotation,k.rotation),h.uniform1f(z.opacity,k.opacity),B(k.blending),L(k.texture,1),h.drawElements(h.TRIANGLES, +6,h.UNSIGNED_SHORT,0)}h.enable(h.CULL_FACE);h.enable(h.DEPTH_TEST);h.depthMask(Q)}function A(b,d){b._modelViewMatrix.multiplyToArray(d.matrixWorldInverse,b.matrixWorld,b._modelViewMatrixArray);THREE.Matrix4.makeInvert3x3(b._modelViewMatrix).transposeIntoArray(b._normalMatrixArray)}function I(b){var d,e,f,g;if(b instanceof THREE.Mesh){e=b.geometry;for(d in e.geometryGroups){f=e.geometryGroups[d];a:{for(var j=g=void 0,k=void 0,m=void 0,o=void 0,o=f.__materials,j=0,k=o.length;j0&&(h.bindBuffer(h.ARRAY_BUFFER,g.__webglColorBuffer),h.bufferData(h.ARRAY_BUFFER,X,k));Wa&&(h.bindBuffer(h.ARRAY_BUFFER,g.__webglNormalBuffer),h.bufferData(h.ARRAY_BUFFER,Z,k));Xa&&ka.hasTangents&& +(h.bindBuffer(h.ARRAY_BUFFER,g.__webglTangentBuffer),h.bufferData(h.ARRAY_BUFFER,U,k));Ja&&W>0&&(h.bindBuffer(h.ARRAY_BUFFER,g.__webglUVBuffer),h.bufferData(h.ARRAY_BUFFER,$,k));Ja&&V>0&&(h.bindBuffer(h.ARRAY_BUFFER,g.__webglUV2Buffer),h.bufferData(h.ARRAY_BUFFER,ca,k));Va&&(h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,g.__webglFaceBuffer),h.bufferData(h.ELEMENT_ARRAY_BUFFER,ra,k),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,g.__webglLineBuffer),h.bufferData(h.ELEMENT_ARRAY_BUFFER,sa,k));K>0&&(h.bindBuffer(h.ARRAY_BUFFER, +g.__webglSkinVertexABuffer),h.bufferData(h.ARRAY_BUFFER,da,k),h.bindBuffer(h.ARRAY_BUFFER,g.__webglSkinVertexBBuffer),h.bufferData(h.ARRAY_BUFFER,fa,k),h.bindBuffer(h.ARRAY_BUFFER,g.__webglSkinIndicesBuffer),h.bufferData(h.ARRAY_BUFFER,ga,k),h.bindBuffer(h.ARRAY_BUFFER,g.__webglSkinWeightsBuffer),h.bufferData(h.ARRAY_BUFFER,ha,k));j.dynamic||(delete g.__inittedArrays,delete g.__colorArray,delete g.__normalArray,delete g.__tangentArray,delete g.__uvArray,delete g.__uv2Array,delete g.__faceArray,delete g.__vertexArray, +delete g.__lineArray,delete g.__skinVertexAArray,delete g.__skinVertexBArray,delete g.__skinIndexArray,delete g.__skinWeightArray)}}e.__dirtyVertices=!1;e.__dirtyMorphTargets=!1;e.__dirtyElements=!1;e.__dirtyUvs=!1;e.__dirtyNormals=!1;e.__dirtyTangents=!1;e.__dirtyColors=!1;var ma;f=f.__materials;e=0;for(b=f.length;e=0;c--)b[c].object==d&&b.splice(c,1)}function G(b){function d(b){var g=[];c=0;for(e=b.length;c65535&&(m[k].counter+=1,n=m[k].hash+"_"+m[k].counter,b.geometryGroups[n]==void 0&&(b.geometryGroups[n]={faces:[],materials:j,vertices:0,numMorphTargets:p})),b.geometryGroups[n].faces.push(g), +b.geometryGroups[n].vertices+=h}function F(b,d,c){b.push({buffer:d,object:c,opaque:{list:[],count:0},transparent:{list:[],count:0}})}function B(b){if(b!=V){switch(b){case THREE.AdditiveBlending:h.blendEquation(h.FUNC_ADD);h.blendFunc(h.SRC_ALPHA,h.ONE);break;case THREE.SubtractiveBlending:h.blendEquation(h.FUNC_ADD);h.blendFunc(h.ZERO,h.ONE_MINUS_SRC_COLOR);break;case THREE.MultiplyBlending:h.blendEquation(h.FUNC_ADD);h.blendFunc(h.ZERO,h.SRC_COLOR);break;default:h.blendEquationSeparate(h.FUNC_ADD, +h.FUNC_ADD),h.blendFuncSeparate(h.SRC_ALPHA,h.ONE_MINUS_SRC_ALPHA,h.ONE,h.ONE_MINUS_SRC_ALPHA)}V=b}}function M(b,d,c){(c.width&c.width-1)==0&&(c.height&c.height-1)==0?(h.texParameteri(b,h.TEXTURE_WRAP_S,S(d.wrapS)),h.texParameteri(b,h.TEXTURE_WRAP_T,S(d.wrapT)),h.texParameteri(b,h.TEXTURE_MAG_FILTER,S(d.magFilter)),h.texParameteri(b,h.TEXTURE_MIN_FILTER,S(d.minFilter)),h.generateMipmap(b)):(h.texParameteri(b,h.TEXTURE_WRAP_S,h.CLAMP_TO_EDGE),h.texParameteri(b,h.TEXTURE_WRAP_T,h.CLAMP_TO_EDGE),h.texParameteri(b, +h.TEXTURE_MAG_FILTER,W(d.magFilter)),h.texParameteri(b,h.TEXTURE_MIN_FILTER,W(d.minFilter)))}function L(b,d){if(b.needsUpdate)b.__webglInit?(h.bindTexture(h.TEXTURE_2D,b.__webglTexture),h.texSubImage2D(h.TEXTURE_2D,0,0,0,h.RGBA,h.UNSIGNED_BYTE,b.image)):(b.__webglTexture=h.createTexture(),h.bindTexture(h.TEXTURE_2D,b.__webglTexture),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,b.image),b.__webglInit=!0),M(h.TEXTURE_2D,b,b.image),h.bindTexture(h.TEXTURE_2D,null),b.needsUpdate=!1;h.activeTexture(h.TEXTURE0+ +d);h.bindTexture(h.TEXTURE_2D,b.__webglTexture)}function O(b){if(b&&!b.__webglFramebuffer){if(b.depthBuffer===void 0)b.depthBuffer=!0;if(b.stencilBuffer===void 0)b.stencilBuffer=!0;b.__webglFramebuffer=h.createFramebuffer();b.__webglRenderbuffer=h.createRenderbuffer();b.__webglTexture=h.createTexture();h.bindTexture(h.TEXTURE_2D,b.__webglTexture);h.texParameteri(h.TEXTURE_2D,h.TEXTURE_WRAP_S,S(b.wrapS));h.texParameteri(h.TEXTURE_2D,h.TEXTURE_WRAP_T,S(b.wrapT));h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER, +S(b.magFilter));h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,S(b.minFilter));h.texImage2D(h.TEXTURE_2D,0,S(b.format),b.width,b.height,0,S(b.format),S(b.type),null);h.bindRenderbuffer(h.RENDERBUFFER,b.__webglRenderbuffer);h.bindFramebuffer(h.FRAMEBUFFER,b.__webglFramebuffer);h.framebufferTexture2D(h.FRAMEBUFFER,h.COLOR_ATTACHMENT0,h.TEXTURE_2D,b.__webglTexture,0);b.depthBuffer&&!b.stencilBuffer?(h.renderbufferStorage(h.RENDERBUFFER,h.DEPTH_COMPONENT16,b.width,b.height),h.framebufferRenderbuffer(h.FRAMEBUFFER, +h.DEPTH_ATTACHMENT,h.RENDERBUFFER,b.__webglRenderbuffer)):b.depthBuffer&&b.stencilBuffer?(h.renderbufferStorage(h.RENDERBUFFER,h.DEPTH_STENCIL,b.width,b.height),h.framebufferRenderbuffer(h.FRAMEBUFFER,h.DEPTH_STENCIL_ATTACHMENT,h.RENDERBUFFER,b.__webglRenderbuffer)):h.renderbufferStorage(h.RENDERBUFFER,h.RGBA4,b.width,b.height);h.bindTexture(h.TEXTURE_2D,null);h.bindRenderbuffer(h.RENDERBUFFER,null);h.bindFramebuffer(h.FRAMEBUFFER,null)}var d,c;b?(d=b.__webglFramebuffer,c=b.width,b=b.height):(d=null, +c=_viewportWidth,b=_viewportHeight);d!=P&&(h.bindFramebuffer(h.FRAMEBUFFER,d),h.viewport(_viewportX,_viewportY,c,b),P=d)}function w(b,d){var c;b=="fragment"?c=h.createShader(h.FRAGMENT_SHADER):b=="vertex"&&(c=h.createShader(h.VERTEX_SHADER));h.shaderSource(c,d);h.compileShader(c);if(!h.getShaderParameter(c,h.COMPILE_STATUS))return console.error(h.getShaderInfoLog(c)),console.error(d),null;return c}function W(b){switch(b){case THREE.NearestFilter:case THREE.NearestMipMapNearestFilter:case THREE.NearestMipMapLinearFilter:return h.NEAREST; +default:return h.LINEAR}}function S(b){switch(b){case THREE.RepeatWrapping:return h.REPEAT;case THREE.ClampToEdgeWrapping:return h.CLAMP_TO_EDGE;case THREE.MirroredRepeatWrapping:return h.MIRRORED_REPEAT;case THREE.NearestFilter:return h.NEAREST;case THREE.NearestMipMapNearestFilter:return h.NEAREST_MIPMAP_NEAREST;case THREE.NearestMipMapLinearFilter:return h.NEAREST_MIPMAP_LINEAR;case THREE.LinearFilter:return h.LINEAR;case THREE.LinearMipMapNearestFilter:return h.LINEAR_MIPMAP_NEAREST;case THREE.LinearMipMapLinearFilter:return h.LINEAR_MIPMAP_LINEAR; +case THREE.ByteType:return h.BYTE;case THREE.UnsignedByteType:return h.UNSIGNED_BYTE;case THREE.ShortType:return h.SHORT;case THREE.UnsignedShortType:return h.UNSIGNED_SHORT;case THREE.IntType:return h.INT;case THREE.UnsignedShortType:return h.UNSIGNED_INT;case THREE.FloatType:return h.FLOAT;case THREE.AlphaFormat:return h.ALPHA;case THREE.RGBFormat:return h.RGB;case THREE.RGBAFormat:return h.RGBA;case THREE.LuminanceFormat:return h.LUMINANCE;case THREE.LuminanceAlphaFormat:return h.LUMINANCE_ALPHA}return 0} +var T=this,h,R=[],J=null,P=null,Q=!0,N=null,Y=null,V=null,Z=null,U=null;_oldPolygonOffsetUnits=_oldPolygonOffsetFactor=null;_cullEnabled=!0;_viewportHeight=_viewportWidth=_viewportY=_viewportX=0;_frustum=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4];_projScreenMatrix=new THREE.Matrix4;_projectionMatrixArray=new Float32Array(16);_viewMatrixArray=new Float32Array(16);_vector3=new THREE.Vector4;_lights={ambient:[0,0,0],directional:{length:0, +colors:[],positions:[]},point:{length:0,colors:[],positions:[],distances:[]}};b=b||{};_canvas=b.canvas!==void 0?b.canvas:document.createElement("canvas");_stencil=b.stencil!==void 0?b.stencil:!0;_antialias=b.antialias!==void 0?b.antialias:!1;_clearColor=b.clearColor!==void 0?new THREE.Color(b.clearColor):new THREE.Color(0);_clearAlpha=b.clearAlpha!==void 0?b.clearAlpha:0;this.data={vertices:0,faces:0,drawCalls:0};this.maxMorphTargets=8;this.domElement=_canvas;this.sortObjects=this.autoClear=!0;try{if(!(h= +_canvas.getContext("experimental-webgl",{antialias:_antialias,stencil:_stencil})))throw"Error creating WebGL context.";}catch(ea){console.error(ea)}console.log(navigator.userAgent+" | "+h.getParameter(h.VERSION)+" | "+h.getParameter(h.VENDOR)+" | "+h.getParameter(h.RENDERER)+" | "+h.getParameter(h.SHADING_LANGUAGE_VERSION));h.clearColor(0,0,0,1);h.clearDepth(1);h.enable(h.DEPTH_TEST);h.depthFunc(h.LEQUAL);h.frontFace(h.CCW);h.cullFace(h.BACK);h.enable(h.CULL_FACE);h.enable(h.BLEND);h.blendEquation(h.FUNC_ADD); +h.blendFunc(h.SRC_ALPHA,h.ONE_MINUS_SRC_ALPHA);h.clearColor(_clearColor.r,_clearColor.g,_clearColor.b,_clearAlpha);_cullEnabled=!0;this.context=h;var ia=h.getParameter(h.MAX_VERTEX_TEXTURE_IMAGE_UNITS)>0;if(_stencil){var D={};D.vertices=new Float32Array(12);D.faces=new Uint16Array(6);D.darkness=0.5;D.vertices[0]=-20;D.vertices[1]=-20;D.vertices[2]=-1;D.vertices[3]=20;D.vertices[4]=-20;D.vertices[5]=-1;D.vertices[6]=20;D.vertices[7]=20;D.vertices[8]=-1;D.vertices[9]=-20;D.vertices[10]=20;D.vertices[11]= +-1;D.faces[0]=0;D.faces[1]=1;D.faces[2]=2;D.faces[3]=0;D.faces[4]=2;D.faces[5]=3;D.vertexBuffer=h.createBuffer();D.elementBuffer=h.createBuffer();h.bindBuffer(h.ARRAY_BUFFER,D.vertexBuffer);h.bufferData(h.ARRAY_BUFFER,D.vertices,h.STATIC_DRAW);h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,D.elementBuffer);h.bufferData(h.ELEMENT_ARRAY_BUFFER,D.faces,h.STATIC_DRAW);D.program=h.createProgram();h.attachShader(D.program,w("fragment",THREE.ShaderLib.shadowPost.fragmentShader));h.attachShader(D.program,w("vertex", +THREE.ShaderLib.shadowPost.vertexShader));h.linkProgram(D.program);D.vertexLocation=h.getAttribLocation(D.program,"position");D.projectionLocation=h.getUniformLocation(D.program,"projectionMatrix");D.darknessLocation=h.getUniformLocation(D.program,"darkness")}var H={};H.vertices=new Float32Array(16);H.faces=new Uint16Array(6);b=0;H.vertices[b++]=-1;H.vertices[b++]=-1;H.vertices[b++]=0;H.vertices[b++]=0;H.vertices[b++]=1;H.vertices[b++]=-1;H.vertices[b++]=1;H.vertices[b++]=0;H.vertices[b++]=1;H.vertices[b++]= +1;H.vertices[b++]=1;H.vertices[b++]=1;H.vertices[b++]=-1;H.vertices[b++]=1;H.vertices[b++]=0;H.vertices[b++]=1;b=0;H.faces[b++]=0;H.faces[b++]=1;H.faces[b++]=2;H.faces[b++]=0;H.faces[b++]=2;H.faces[b++]=3;H.vertexBuffer=h.createBuffer();H.elementBuffer=h.createBuffer();H.tempTexture=h.createTexture();H.occlusionTexture=h.createTexture();h.bindBuffer(h.ARRAY_BUFFER,H.vertexBuffer);h.bufferData(h.ARRAY_BUFFER,H.vertices,h.STATIC_DRAW);h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,H.elementBuffer);h.bufferData(h.ELEMENT_ARRAY_BUFFER, +H.faces,h.STATIC_DRAW);h.bindTexture(h.TEXTURE_2D,H.tempTexture);h.texImage2D(h.TEXTURE_2D,0,h.RGB,16,16,0,h.RGB,h.UNSIGNED_BYTE,null);h.texParameteri(h.TEXTURE_2D,h.TEXTURE_WRAP_S,h.CLAMP_TO_EDGE);h.texParameteri(h.TEXTURE_2D,h.TEXTURE_WRAP_T,h.CLAMP_TO_EDGE);h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.NEAREST);h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.NEAREST);h.bindTexture(h.TEXTURE_2D,H.occlusionTexture);h.texImage2D(h.TEXTURE_2D,0,h.RGBA,16,16,0,h.RGBA,h.UNSIGNED_BYTE,null); +h.texParameteri(h.TEXTURE_2D,h.TEXTURE_WRAP_S,h.CLAMP_TO_EDGE);h.texParameteri(h.TEXTURE_2D,h.TEXTURE_WRAP_T,h.CLAMP_TO_EDGE);h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.NEAREST);h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.NEAREST);h.getParameter(h.MAX_VERTEX_TEXTURE_IMAGE_UNITS)<=0?(H.hasVertexTexture=!1,H.program=h.createProgram(),h.attachShader(H.program,w("fragment",THREE.ShaderLib.lensFlare.fragmentShader)),h.attachShader(H.program,w("vertex",THREE.ShaderLib.lensFlare.vertexShader))): +(H.hasVertexTexture=!0,H.program=h.createProgram(),h.attachShader(H.program,w("fragment",THREE.ShaderLib.lensFlareVertexTexture.fragmentShader)),h.attachShader(H.program,w("vertex",THREE.ShaderLib.lensFlareVertexTexture.vertexShader)));h.linkProgram(H.program);H.attributes={};H.uniforms={};H.attributes.vertex=h.getAttribLocation(H.program,"position");H.attributes.uv=h.getAttribLocation(H.program,"UV");H.uniforms.renderType=h.getUniformLocation(H.program,"renderType");H.uniforms.map=h.getUniformLocation(H.program, +"map");H.uniforms.occlusionMap=h.getUniformLocation(H.program,"occlusionMap");H.uniforms.opacity=h.getUniformLocation(H.program,"opacity");H.uniforms.scale=h.getUniformLocation(H.program,"scale");H.uniforms.rotation=h.getUniformLocation(H.program,"rotation");H.uniforms.screenPosition=h.getUniformLocation(H.program,"screenPosition");var $=!1;_sprite={};_sprite.vertices=new Float32Array(16);_sprite.faces=new Uint16Array(6);b=0;_sprite.vertices[b++]=-1;_sprite.vertices[b++]=-1;_sprite.vertices[b++]= +0;_sprite.vertices[b++]=0;_sprite.vertices[b++]=1;_sprite.vertices[b++]=-1;_sprite.vertices[b++]=1;_sprite.vertices[b++]=0;_sprite.vertices[b++]=1;_sprite.vertices[b++]=1;_sprite.vertices[b++]=1;_sprite.vertices[b++]=1;_sprite.vertices[b++]=-1;_sprite.vertices[b++]=1;_sprite.vertices[b++]=0;_sprite.vertices[b++]=1;b=0;_sprite.faces[b++]=0;_sprite.faces[b++]=1;_sprite.faces[b++]=2;_sprite.faces[b++]=0;_sprite.faces[b++]=2;_sprite.faces[b++]=3;_sprite.vertexBuffer=h.createBuffer();_sprite.elementBuffer= +h.createBuffer();h.bindBuffer(h.ARRAY_BUFFER,_sprite.vertexBuffer);h.bufferData(h.ARRAY_BUFFER,_sprite.vertices,h.STATIC_DRAW);h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,_sprite.elementBuffer);h.bufferData(h.ELEMENT_ARRAY_BUFFER,_sprite.faces,h.STATIC_DRAW);_sprite.program=h.createProgram();h.attachShader(_sprite.program,w("fragment",THREE.ShaderLib.sprite.fragmentShader));h.attachShader(_sprite.program,w("vertex",THREE.ShaderLib.sprite.vertexShader));h.linkProgram(_sprite.program);_sprite.attributes={}; +_sprite.uniforms={};_sprite.attributes.position=h.getAttribLocation(_sprite.program,"position");_sprite.attributes.uv=h.getAttribLocation(_sprite.program,"uv");_sprite.uniforms.uvOffset=h.getUniformLocation(_sprite.program,"uvOffset");_sprite.uniforms.uvScale=h.getUniformLocation(_sprite.program,"uvScale");_sprite.uniforms.rotation=h.getUniformLocation(_sprite.program,"rotation");_sprite.uniforms.scale=h.getUniformLocation(_sprite.program,"scale");_sprite.uniforms.alignment=h.getUniformLocation(_sprite.program, +"alignment");_sprite.uniforms.map=h.getUniformLocation(_sprite.program,"map");_sprite.uniforms.opacity=h.getUniformLocation(_sprite.program,"opacity");_sprite.uniforms.useScreenCoordinates=h.getUniformLocation(_sprite.program,"useScreenCoordinates");_sprite.uniforms.affectedByDistance=h.getUniformLocation(_sprite.program,"affectedByDistance");_sprite.uniforms.screenPosition=h.getUniformLocation(_sprite.program,"screenPosition");_sprite.uniforms.modelViewMatrix=h.getUniformLocation(_sprite.program, +"modelViewMatrix");_sprite.uniforms.projectionMatrix=h.getUniformLocation(_sprite.program,"projectionMatrix");var ca=!1;this.setSize=function(b,d){_canvas.width=b;_canvas.height=d;this.setViewport(0,0,_canvas.width,_canvas.height)};this.setViewport=function(b,d,c,e){_viewportX=b;_viewportY=d;_viewportWidth=c;_viewportHeight=e;h.viewport(_viewportX,_viewportY,_viewportWidth,_viewportHeight)};this.setScissor=function(b,d,c,e){h.scissor(b,d,c,e)};this.enableScissorTest=function(b){b?h.enable(h.SCISSOR_TEST): +h.disable(h.SCISSOR_TEST)};this.enableDepthBufferWrite=function(b){Q=b;h.depthMask(b)};this.setClearColorHex=function(b,d){_clearColor.setHex(b);_clearAlpha=d;h.clearColor(_clearColor.r,_clearColor.g,_clearColor.b,_clearAlpha)};this.setClearColor=function(b,d){_clearColor.copy(b);_clearAlpha=d;h.clearColor(_clearColor.r,_clearColor.g,_clearColor.b,_clearAlpha)};this.clear=function(){h.clear(h.COLOR_BUFFER_BIT|h.DEPTH_BUFFER_BIT|h.STENCIL_BUFFER_BIT)};this.setStencilShadowDarkness=function(b){D.darkness= +b};this.getContext=function(){return h};this.initMaterial=function(b,d,c,e){var g,f,j;b instanceof THREE.MeshDepthMaterial?j="depth":b instanceof THREE.ShadowVolumeDynamicMaterial?j="shadowVolumeDynamic":b instanceof THREE.MeshNormalMaterial?j="normal":b instanceof THREE.MeshBasicMaterial?j="basic":b instanceof THREE.MeshLambertMaterial?j="lambert":b instanceof THREE.MeshPhongMaterial?j="phong":b instanceof THREE.LineBasicMaterial?j="basic":b instanceof THREE.ParticleBasicMaterial&&(j="particle_basic"); +if(j){var k=THREE.ShaderLib[j];b.uniforms=THREE.UniformsUtils.clone(k.uniforms);b.vertexShader=k.vertexShader;b.fragmentShader=k.fragmentShader}var n,m,p;n=p=k=0;for(m=d.length;n=0&&h.enableVertexAttribArray(o.position);o.color>=0&&h.enableVertexAttribArray(o.color);o.normal>= +0&&h.enableVertexAttribArray(o.normal);o.tangent>=0&&h.enableVertexAttribArray(o.tangent);b.skinning&&o.skinVertexA>=0&&o.skinVertexB>=0&&o.skinIndex>=0&&o.skinWeight>=0&&(h.enableVertexAttribArray(o.skinVertexA),h.enableVertexAttribArray(o.skinVertexB),h.enableVertexAttribArray(o.skinIndex),h.enableVertexAttribArray(o.skinWeight));if(b.attributes)for(g in b.attributes)o[g]!==void 0&&o[g]>=0&&h.enableVertexAttribArray(o[g]);if(b.morphTargets){b.numSupportedMorphTargets=0;o.morphTarget0>=0&&(h.enableVertexAttribArray(o.morphTarget0), +b.numSupportedMorphTargets++);o.morphTarget1>=0&&(h.enableVertexAttribArray(o.morphTarget1),b.numSupportedMorphTargets++);o.morphTarget2>=0&&(h.enableVertexAttribArray(o.morphTarget2),b.numSupportedMorphTargets++);o.morphTarget3>=0&&(h.enableVertexAttribArray(o.morphTarget3),b.numSupportedMorphTargets++);o.morphTarget4>=0&&(h.enableVertexAttribArray(o.morphTarget4),b.numSupportedMorphTargets++);o.morphTarget5>=0&&(h.enableVertexAttribArray(o.morphTarget5),b.numSupportedMorphTargets++);o.morphTarget6>= +0&&(h.enableVertexAttribArray(o.morphTarget6),b.numSupportedMorphTargets++);o.morphTarget7>=0&&(h.enableVertexAttribArray(o.morphTarget7),b.numSupportedMorphTargets++);e.__webglMorphTargetInfluences=new Float32Array(this.maxMorphTargets);b=0;for(g=this.maxMorphTargets;b0||t.faceVertexUvs.length>0)j.__uvArray=new Float32Array(n*2);if(t.faceUvs.length>1||t.faceVertexUvs.length>1)j.__uv2Array=new Float32Array(n*2)}if(k.geometry.skinWeights.length&&k.geometry.skinIndices.length)j.__skinVertexAArray=new Float32Array(n*4),j.__skinVertexBArray=new Float32Array(n*4),j.__skinIndexArray=new Float32Array(n*4),j.__skinWeightArray=new Float32Array(n*4);j.__faceArray=new Uint16Array(v*3+(k.geometry.edgeFaces?k.geometry.edgeFaces.length* +6:0));j.__lineArray=new Uint16Array(A*2);if(j.numMorphTargets){j.__morphTargetsArrays=[];t=0;for(u=j.numMorphTargets;t=0;g--)d[g]==c&&d.splice(g,1)}else c instanceof THREE.LensFlare?y(d.__webglLensFlares,c):c instanceof THREE.MarchingCubes&&y(d.__webglObjectsImmediate,c);b.__objectsRemoved.splice(0,1)}d=0;for(c=b.__webglObjects.length;d1&&(d-=1)}c===void 0&&(c={h:0,s:0,v:0});c.h=d;c.s=j;c.v=g;return c}, +clamp:function(b,c,d){return bd?d:b}};THREE.ColorUtils.__hsv={h:0,s:0,v:0}; +var GeometryUtils={merge:function(b,c){var d=c instanceof THREE.Mesh,e=b.vertices.length,f=d?c.geometry:c,g=b.vertices,j=f.vertices,k=b.faces,m=f.faces,o=b.faceVertexUvs[0],f=f.faceVertexUvs[0];d&&c.matrixAutoUpdate&&c.updateMatrix();for(var n=0,t=j.length;n= 0.0 )\npointSpecularWeight = specularTex.r * pow( pointDotNormalHalf, uShininess );\npointDiffuse += vec4( uDiffuseColor, 1.0 ) * pointDiffuseWeight;\npointSpecular += vec4( uSpecularColor, 1.0 ) * pointSpecularWeight * pointDiffuseWeight;\nvec4 dirDiffuse = vec4( 0.0, 0.0, 0.0, 0.0 );\nvec4 dirSpecular = vec4( 0.0, 0.0, 0.0, 0.0 );\nvec4 lDirection = viewMatrix * vec4( uDirLightPos, 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nvec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );\nfloat dirDotNormalHalf = dot( normal, dirHalfVector );\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\nfloat dirSpecularWeight = 0.0;\nif ( dirDotNormalHalf >= 0.0 )\ndirSpecularWeight = specularTex.r * pow( dirDotNormalHalf, uShininess );\ndirDiffuse += vec4( uDiffuseColor, 1.0 ) * dirDiffuseWeight;\ndirSpecular += vec4( uSpecularColor, 1.0 ) * dirSpecularWeight * dirDiffuseWeight;\nvec4 totalLight = vec4( uAmbientLightColor * uAmbientColor, 1.0 );\ntotalLight += vec4( uDirLightColor, 1.0 ) * ( dirDiffuse + dirSpecular );\ntotalLight += vec4( uPointLightColor, 1.0 ) * ( pointDiffuse + pointSpecular );\ngl_FragColor = vec4( totalLight.xyz * aoTex * diffuseTex, 1.0 );\n}", +vertexShader:"attribute vec4 tangent;\nuniform vec3 uPointLightPos;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\nvarying vec3 vPointLightVector;\nvarying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvNormal = normalize( normalMatrix * normal );\nvTangent = normalize( normalMatrix * tangent.xyz );\nvBinormal = cross( vNormal, vTangent ) * tangent.w;\nvBinormal = normalize( vBinormal );\nvUv = uv;\nvec4 lPosition = viewMatrix * vec4( uPointLightPos, 1.0 );\nvPointLightVector = normalize( lPosition.xyz - mvPosition.xyz );\n#ifdef VERTEX_TEXTURES\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\nvec4 displacedPosition = vec4( vNormal.xyz * df, 0.0 ) + mvPosition;\ngl_Position = projectionMatrix * displacedPosition;\n#else\ngl_Position = projectionMatrix * mvPosition;\n#endif\n}"}, +cube:{uniforms:{tCube:{type:"t",value:1,texture:null}},vertexShader:"varying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nvarying vec3 vViewPosition;\nvoid main() {\nvec3 wPos = cameraPosition - vViewPosition;\ngl_FragColor = textureCube( tCube, vec3( - wPos.x, wPos.yz ) );\n}"},convolution:{uniforms:{tDiffuse:{type:"t", +value:0,texture:null},uImageIncrement:{type:"v2",value:new THREE.Vector2(0.001953125,0)},cKernel:{type:"fv1",value:[]}},vertexShader:"varying vec2 vUv;\nuniform vec2 uImageIncrement;\nvoid main(void) {\nvUv = uv - ((KERNEL_SIZE - 1.0) / 2.0) * uImageIncrement;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"varying vec2 vUv;\nuniform sampler2D tDiffuse;\nuniform vec2 uImageIncrement;\nuniform float cKernel[KERNEL_SIZE];\nvoid main(void) {\nvec2 imageCoord = vUv;\nvec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );\nfor( int i=0; i25&&(g=25);f=(g-1)*0.5;d=Array(g);for(c=e=0;c1)console.log("THREE.Animation.update: Warning! Scale out of bounds:"+e+" on bone "+u),e=e<0?0:1;if(d==="pos")if(d=b.position,this.interpolationType===THREE.AnimationHandler.LINEAR)d.x=f[0]+(g[0]-f[0])*e,d.y=f[1]+(g[1]-f[1])*e,d.z=f[2]+(g[2]-f[2])*e;else{if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD)if(this.points[0]= +this.getPrevKeyWith("pos",u,j.index-1).pos,this.points[1]=f,this.points[2]=g,this.points[3]=this.getNextKeyWith("pos",u,k.index+1).pos,e=e*0.33+0.33,f=this.interpolateCatmullRom(this.points,e),d.x=f[0],d.y=f[1],d.z=f[2],this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD)e=this.interpolateCatmullRom(this.points,e*1.01),this.target.set(e[0],e[1],e[2]),this.target.subSelf(d),this.target.y=0,this.target.normalize(),e=Math.atan2(this.target.x,this.target.z),b.rotation.set(0,e,0)}else if(d=== +"rot")THREE.Quaternion.slerp(f,g,b.quaternion,e);else if(d==="scl")d=b.scale,d.x=f[0]+(g[0]-f[0])*e,d.y=f[1]+(g[1]-f[1])*e,d.z=f[2]+(g[2]-f[2])*e}}if(this.JITCompile&&n[0][o]===void 0){this.hierarchy[0].update(void 0,!0);for(u=0;ub.length-2?g:g+1;d[3]=g>b.length-3?g:g+2;g=b[d[0]];k=b[d[1]];m=b[d[2]];o=b[d[3]];d=f*f;j=f*d;e[0]=this.interpolate(g[0],k[0],m[0],o[0],f,d,j);e[1]=this.interpolate(g[1],k[1],m[1],o[1],f,d,j);e[2]=this.interpolate(g[2],k[2],m[2],o[2],f,d,j);return e}; +THREE.Animation.prototype.interpolate=function(b,c,d,e,f,g,j){b=(d-b)*0.5;e=(e-c)*0.5;return(2*(c-d)+b+e)*j+(-3*(c-d)-2*b-e)*g+b*f+c};THREE.Animation.prototype.getNextKeyWith=function(b,c,d){var e=this.data.hierarchy[c].keys;for(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?d=d0?d:0:d>=0?d:d+e.length;d>=0;d--)if(e[d][b]!==void 0)return e[d];return this.data.hierarchy[c].keys[e.length-1]}; +THREE.FPCamera=function(b){function c(b,c){return function(){c.apply(b,arguments)}}THREE.Camera.call(this,b.fov,b.aspect,b.near,b.far,b.target);this.movementSpeed=1;this.lookSpeed=0.005;this.noFly=!1;this.lookVertical=!0;this.autoForward=!1;this.activeLook=!0;this.heightSpeed=!1;this.heightCoef=1;this.heightMin=0;this.constrainVertical=!1;this.verticalMin=0;this.verticalMax=3.14;this.domElement=document;this.lastUpdate=(new Date).getTime();this.tdiff=0;if(b){if(b.movementSpeed!==void 0)this.movementSpeed= +b.movementSpeed;if(b.lookSpeed!==void 0)this.lookSpeed=b.lookSpeed;if(b.noFly!==void 0)this.noFly=b.noFly;if(b.lookVertical!==void 0)this.lookVertical=b.lookVertical;if(b.autoForward!==void 0)this.autoForward=b.autoForward;if(b.activeLook!==void 0)this.activeLook=b.activeLook;if(b.heightSpeed!==void 0)this.heightSpeed=b.heightSpeed;if(b.heightCoef!==void 0)this.heightCoef=b.heightCoef;if(b.heightMin!==void 0)this.heightMin=b.heightMin;if(b.heightMax!==void 0)this.heightMax=b.heightMax;if(b.constrainVertical!== +void 0)this.constrainVertical=b.constrainVertical;if(b.verticalMin!==void 0)this.verticalMin=b.verticalMin;if(b.verticalMax!==void 0)this.verticalMax=b.verticalMax;if(b.domElement!==void 0)this.domElement=b.domElement}this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX=this.autoSpeedFactor=0;this.mouseDragOn=this.freeze=this.moveRight=this.moveLeft=this.moveBackward=this.moveForward=!1;this.windowHalfX=window.innerWidth/2;this.windowHalfY=window.innerHeight/2;this.onMouseDown=function(b){b.preventDefault(); +b.stopPropagation();if(this.activeLook)switch(b.button){case 0:this.moveForward=!0;break;case 2:this.moveBackward=!0}this.mouseDragOn=!0};this.onMouseUp=function(b){b.preventDefault();b.stopPropagation();if(this.activeLook)switch(b.button){case 0:this.moveForward=!1;break;case 2:this.moveBackward=!1}this.mouseDragOn=!1};this.onMouseMove=function(b){this.mouseX=b.clientX-this.windowHalfX;this.mouseY=b.clientY-this.windowHalfY};this.onKeyDown=function(b){switch(b.keyCode){case 38:case 87:this.moveForward= +!0;break;case 37:case 65:this.moveLeft=!0;break;case 40:case 83:this.moveBackward=!0;break;case 39:case 68:this.moveRight=!0;break;case 81:this.freeze=!this.freeze}};this.onKeyUp=function(b){switch(b.keyCode){case 38:case 87:this.moveForward=!1;break;case 37:case 65:this.moveLeft=!1;break;case 40:case 83:this.moveBackward=!1;break;case 39:case 68:this.moveRight=!1}};this.update=function(){var b=(new Date).getTime();this.tdiff=(b-this.lastUpdate)/1E3;this.lastUpdate=b;if(!this.freeze){this.autoSpeedFactor= +this.heightSpeed?this.tdiff*((this.position.ythis.heightMax?this.heightMax:this.position.y)-this.heightMin)*this.heightCoef:0;var c=this.tdiff*this.movementSpeed;(this.moveForward||this.autoForward&&!this.moveBackward)&&this.translateZ(-(c+this.autoSpeedFactor));this.moveBackward&&this.translateZ(c);this.moveLeft&&this.translateX(-c);this.moveRight&&this.translateX(c);c=this.tdiff*this.lookSpeed;this.activeLook||(c=0);this.lon+=this.mouseX*c;this.lookVertical&& +(this.lat-=this.mouseY*c);this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;var b=this.target.position,f=this.position;b.x=f.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=f.y+100*Math.cos(this.phi);b.z=f.z+100*Math.sin(this.phi)*Math.sin(this.theta)}this.lon+=this.mouseX*c;this.lookVertical&&(this.lat-=this.mouseY*c);this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;if(this.constrainVertical)this.phi= +(this.phi-0)*(this.verticalMax-this.verticalMin)/3.14+this.verticalMin;b=this.target.position;f=this.position;b.x=f.x+100*Math.sin(this.phi)*Math.cos(this.theta);b.y=f.y+100*Math.cos(this.phi);b.z=f.z+100*Math.sin(this.phi)*Math.sin(this.theta);this.supr.update.call(this)};this.domElement.addEventListener("contextmenu",function(b){b.preventDefault()},!1);this.domElement.addEventListener("mousemove",c(this,this.onMouseMove),!1);this.domElement.addEventListener("mousedown",c(this,this.onMouseDown), +!1);this.domElement.addEventListener("mouseup",c(this,this.onMouseUp),!1);this.domElement.addEventListener("keydown",c(this,this.onKeyDown),!1);this.domElement.addEventListener("keyup",c(this,this.onKeyUp),!1)};THREE.FPCamera.prototype=new THREE.Camera;THREE.FPCamera.prototype.constructor=THREE.FPCamera;THREE.FPCamera.prototype.supr=THREE.Camera.prototype;THREE.FPCamera.prototype.translate=function(b,c){this.matrix.rotateAxis(c);if(this.noFly)c.y=0;this.position.addSelf(c.multiplyScalar(b));this.target.position.addSelf(c.multiplyScalar(b))}; +THREE.PathCamera=function(b){function c(b,d,c,e){var g={name:c,fps:0.6,length:e,hierarchy:[]},f,j=d.getControlPointsArray(),k=d.getLength(),m=j.length,I=0;f=m-1;d={parent:-1,keys:[]};d.keys[0]={time:0,pos:j[0],rot:[0,0,0,1],scl:[1,1,1]};d.keys[f]={time:e,pos:j[f],rot:[0,0,0,1],scl:[1,1,1]};for(f=1;f=0?e:e+f;e=this.verticalAngleMap.srcRange;j=this.verticalAngleMap.dstRange;var k=j[1]-j[0];this.phi= +TWEEN.Easing.Quadratic.EaseInOut(((this.phi-e[0])*(j[1]-j[0])/(e[1]-e[0])+j[0]-j[0])/k)*k+j[0];e=this.horizontalAngleMap.srcRange;j=this.horizontalAngleMap.dstRange;k=j[1]-j[0];this.theta=TWEEN.Easing.Quadratic.EaseInOut(((this.theta-e[0])*(j[1]-j[0])/(e[1]-e[0])+j[0]-j[0])/k)*k+j[0];e=this.target.position;e.x=100*Math.sin(this.phi)*Math.cos(this.theta);e.y=100*Math.cos(this.phi);e.z=100*Math.sin(this.phi)*Math.sin(this.theta);this.supr.update.call(this,b,d,c)};this.onMouseMove=function(b){this.mouseX= +b.clientX-this.windowHalfX;this.mouseY=b.clientY-this.windowHalfY};this.spline=new THREE.Spline;this.spline.initFromArray(this.waypoints);this.useConstantSpeed&&this.spline.reparametrizeByArcLength(this.resamplingCoef);if(this.createDebugDummy){var b=new THREE.MeshLambertMaterial({color:30719}),j=new THREE.MeshLambertMaterial({color:65280}),k=new THREE.CubeGeometry(10,10,20),m=new THREE.CubeGeometry(2,2,10);this.animationParent=new THREE.Mesh(k,b);b=new THREE.Mesh(m,j);b.position.set(0,10,0);this.animation= +c(this.animationParent,this.spline,this.id,this.duration);this.animationParent.addChild(this);this.animationParent.addChild(this.target);this.animationParent.addChild(b)}else this.animation=c(this.animationParent,this.spline,this.id,this.duration),this.animationParent.addChild(this.target),this.animationParent.addChild(this);this.createDebugPath&&e(this.debugPath,this.spline);this.domElement.addEventListener("mousemove",function(b,d){return function(){d.apply(b,arguments)}}(this,this.onMouseMove), +!1)};THREE.PathCamera.prototype=new THREE.Camera;THREE.PathCamera.prototype.constructor=THREE.PathCamera;THREE.PathCamera.prototype.supr=THREE.Camera.prototype;THREE.PathCameraIdCounter=0; +THREE.FlyCamera=function(b){function c(b,c){return function(){c.apply(b,arguments)}}THREE.Camera.call(this,b.fov,b.aspect,b.near,b.far,b.target);this.tmpQuaternion=new THREE.Quaternion;this.movementSpeed=1;this.rollSpeed=0.005;this.autoForward=this.dragToLook=!1;this.domElement=document;if(b){if(b.movementSpeed!==void 0)this.movementSpeed=b.movementSpeed;if(b.rollSpeed!==void 0)this.rollSpeed=b.rollSpeed;if(b.dragToLook!==void 0)this.dragToLook=b.dragToLook;if(b.autoForward!==void 0)this.autoForward= +b.autoForward;if(b.domElement!==void 0)this.domElement=b.domElement}this.useTarget=!1;this.useQuaternion=!0;this.mouseStatus=0;this.moveState={up:0,down:0,left:0,right:0,forward:0,back:0,pitchUp:0,pitchDown:0,yawLeft:0,yawRight:0,rollLeft:0,rollRight:0};this.moveVector=new THREE.Vector3(0,0,0);this.rotationVector=new THREE.Vector3(0,0,0);this.lastUpdate=-1;this.tdiff=0;this.handleEvent=function(b){if(typeof this[b.type]=="function")this[b.type](b)};this.keydown=function(b){if(!b.altKey){switch(b.keyCode){case 16:this.movementSpeedMultiplier= +0.1;break;case 87:this.moveState.forward=1;break;case 83:this.moveState.back=1;break;case 65:this.moveState.left=1;break;case 68:this.moveState.right=1;break;case 82:this.moveState.up=1;break;case 70:this.moveState.down=1;break;case 38:this.moveState.pitchUp=1;break;case 40:this.moveState.pitchDown=1;break;case 37:this.moveState.yawLeft=1;break;case 39:this.moveState.yawRight=1;break;case 81:this.moveState.rollLeft=1;break;case 69:this.moveState.rollRight=1}this.updateMovementVector();this.updateRotationVector()}}; +this.keyup=function(b){switch(b.keyCode){case 16:this.movementSpeedMultiplier=1;break;case 87:this.moveState.forward=0;break;case 83:this.moveState.back=0;break;case 65:this.moveState.left=0;break;case 68:this.moveState.right=0;break;case 82:this.moveState.up=0;break;case 70:this.moveState.down=0;break;case 38:this.moveState.pitchUp=0;break;case 40:this.moveState.pitchDown=0;break;case 37:this.moveState.yawLeft=0;break;case 39:this.moveState.yawRight=0;break;case 81:this.moveState.rollLeft=0;break; +case 69:this.moveState.rollRight=0}this.updateMovementVector();this.updateRotationVector()};this.mousedown=function(b){b.preventDefault();b.stopPropagation();if(this.dragToLook)this.mouseStatus++;else switch(b.button){case 0:this.moveForward=!0;break;case 2:this.moveBackward=!0}};this.mousemove=function(b){if(!this.dragToLook||this.mouseStatus>0){var c=this.getContainerDimensions(),f=c.size[0]/2,g=c.size[1]/2;this.moveState.yawLeft=-(b.clientX-c.offset[0]-f)/f;this.moveState.pitchDown=(b.clientY- +c.offset[1]-g)/g;this.updateRotationVector()}};this.mouseup=function(b){b.preventDefault();b.stopPropagation();if(this.dragToLook)this.mouseStatus--,this.moveState.yawLeft=this.moveState.pitchDown=0;else switch(b.button){case 0:this.moveForward=!1;break;case 2:this.moveBackward=!1}this.updateRotationVector()};this.update=function(){var b=(new Date).getTime();if(this.lastUpdate==-1)this.lastUpdate=b;this.tdiff=(b-this.lastUpdate)/1E3;this.lastUpdate=b;var b=this.tdiff*this.movementSpeed,c=this.tdiff* +this.rollSpeed;this.translateX(this.moveVector.x*b);this.translateY(this.moveVector.y*b);this.translateZ(this.moveVector.z*b);this.tmpQuaternion.set(this.rotationVector.x*c,this.rotationVector.y*c,this.rotationVector.z*c,1).normalize();this.quaternion.multiplySelf(this.tmpQuaternion);this.matrix.setPosition(this.position);this.matrix.setRotationFromQuaternion(this.quaternion);this.matrixWorldNeedsUpdate=!0;this.supr.update.call(this)};this.updateMovementVector=function(){var b=this.moveState.forward|| +this.autoForward&&!this.moveState.back?1:0;this.moveVector.x=-this.moveState.left+this.moveState.right;this.moveVector.y=-this.moveState.down+this.moveState.up;this.moveVector.z=-b+this.moveState.back};this.updateRotationVector=function(){this.rotationVector.x=-this.moveState.pitchDown+this.moveState.pitchUp;this.rotationVector.y=-this.moveState.yawRight+this.moveState.yawLeft;this.rotationVector.z=-this.moveState.rollRight+this.moveState.rollLeft};this.getContainerDimensions=function(){return this.domElement!= +document?{size:[this.domElement.offsetWidth,this.domElement.offsetHeight],offset:[this.domElement.offsetLeft,this.domElement.offsetTop]}:{size:[window.innerWidth,window.innerHeight],offset:[0,0]}};this.domElement.addEventListener("mousemove",c(this,this.mousemove),!1);this.domElement.addEventListener("mousedown",c(this,this.mousedown),!1);this.domElement.addEventListener("mouseup",c(this,this.mouseup),!1);window.addEventListener("keydown",c(this,this.keydown),!1);window.addEventListener("keyup",c(this, +this.keyup),!1);this.updateMovementVector();this.updateRotationVector()};THREE.FlyCamera.prototype=new THREE.Camera;THREE.FlyCamera.prototype.constructor=THREE.FlyCamera;THREE.FlyCamera.prototype.supr=THREE.Camera.prototype; +THREE.RollCamera=function(b,c,d,e){THREE.Camera.call(this,b,c,d,e);this.mouseLook=!0;this.autoForward=!1;this.rollSpeed=this.movementSpeed=this.lookSpeed=1;this.constrainVertical=[-0.9,0.9];this.domElement=document;this.matrixAutoUpdate=this.useTarget=!1;this.forward=new THREE.Vector3(0,0,1);this.roll=0;this.lastUpdate=-1;this.delta=0;var f=new THREE.Vector3,g=new THREE.Vector3,j=new THREE.Vector3,k=new THREE.Matrix4,m=!1,o=1,n=0,t=0,p=0,u=0,v=0,z=window.innerWidth/2,C=window.innerHeight/2;this.update= +function(){var b=(new Date).getTime();if(this.lastUpdate==-1)this.lastUpdate=b;this.delta=(b-this.lastUpdate)/1E3;this.lastUpdate=b;this.mouseLook&&(b=this.delta*this.lookSpeed,this.rotateHorizontally(b*u),this.rotateVertically(b*v));b=this.delta*this.movementSpeed;this.translateZ(b*(n>0||this.autoForward&&!(n<0)?1:n));this.translateX(b*t);this.translateY(b*p);m&&(this.roll+=this.rollSpeed*this.delta*o);if(this.forward.y>this.constrainVertical[1])this.forward.y=this.constrainVertical[1],this.forward.normalize(); +else if(this.forward.y1?d.normalize():d.z=Math.sqrt(1-e*e);f=this.position.clone().subSelf(this.target.position);e=this.up.clone().setLength(d.y);e.addSelf(this.up.clone().crossSelf(f).setLength(d.x));e.addSelf(f.setLength(d.z));return e}; +this.rotateCamera=function(){var b=Math.acos(g.dot(j)/g.length()/j.length());if(b){var c=(new THREE.Vector3).cross(g,j).normalize(),d=new THREE.Quaternion;b*=this.rotateSpeed;d.setFromAxisAngle(c,-b);d.multiplyVector3(f);d.multiplyVector3(this.up);d.multiplyVector3(j);this.staticMoving?g=j:(d.setFromAxisAngle(c,b*(this.dynamicDampingFactor-1)),d.multiplyVector3(g))}};this.zoomCamera=function(){var b=1+(m.y-k.y)*this.zoomSpeed;b!==1&&b>0&&(f.multiplyScalar(b),this.staticMoving?k=m:k.y+=(m.y-k.y)*this.dynamicDampingFactor)}; +this.panCamera=function(){var b=n.clone().subSelf(o);if(b.lengthSq()){b.multiplyScalar(f.length()*this.panSpeed);var c=f.clone().crossSelf(this.up).setLength(b.x);c.addSelf(this.up.clone().setLength(b.y));this.position.addSelf(c);this.target.position.addSelf(c);this.staticMoving?o=n:o.addSelf(b.sub(n,o).multiplyScalar(this.dynamicDampingFactor))}};this.checkDistances=function(){if(!this.noZoom||!this.noPan)this.position.lengthSq()>this.maxDistance*this.maxDistance&&this.position.setLength(this.maxDistance), +f.lengthSq()0){j(0,0,-n-(g||0));for(m=b;m0){j(0,0,n+ +(f||0));for(m=b+b/2;m<2*b;m++)k.faces.push(new THREE.Face4(2*b+1,(2*m-2*b+2)%b+b,(2*m-2*b+1)%b+b,(2*m-2*b)%b+b))}m=0;for(b=this.faces.length;m0||(n=this.vertices.push(new THREE.Vertex(new THREE.Vector3(t,k,p)))-1);o.push(n)}c.push(o)}for(var u,v,z,f=c.length,d=0;d0)for(e=0;e1&&(u= +this.vertices[j].position.clone(),v=this.vertices[m].position.clone(),z=this.vertices[o].position.clone(),u.normalize(),v.normalize(),z.normalize(),this.faces.push(new THREE.Face3(j,m,o,[new THREE.Vector3(u.x,u.y,u.z),new THREE.Vector3(v.x,v.y,v.z),new THREE.Vector3(z.x,z.y,z.z)])),this.faceVertexUvs[0].push([n,t,C]))}this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals();this.boundingSphere={radius:b}};THREE.SphereGeometry.prototype=new THREE.Geometry; +THREE.SphereGeometry.prototype.constructor=THREE.SphereGeometry;THREE.TextGeometry=function(b,c){THREE.Geometry.call(this);this.parameters=c||{};this.set(b)};THREE.TextGeometry.prototype=new THREE.Geometry;THREE.TextGeometry.prototype.constructor=THREE.TextGeometry; +THREE.TextGeometry.prototype.set=function(b,c){function d(b,c,d){v.vertices.push(new THREE.Vertex(new THREE.Vector3(b,c,d)))}function e(b,c,d,e){v.faces.push(new THREE.Face4(b,c,d,e))}this.text=b;var c=c||this.parameters,f=c.height!==void 0?c.height:50,g=c.curveSegments!==void 0?c.curveSegments:4,j=c.font!==void 0?c.font:"helvetiker",k=c.weight!==void 0?c.weight:"normal",m=c.style!==void 0?c.style:"normal",o=c.bezelThickness!==void 0?c.bezelThickness:10,n=c.bezelSize!==void 0?c.bezelSize:8,t=c.bezelEnabled!== +void 0?c.bezelEnabled:!1;THREE.FontUtils.size=c.size!==void 0?c.size:100;THREE.FontUtils.divisions=g;THREE.FontUtils.face=j;THREE.FontUtils.weight=k;THREE.FontUtils.style=m;THREE.FontUtils.bezelSize=n;var k=THREE.FontUtils.drawText(b),g=k.points,p=k.faces,j=k.contour,u=k.bezel,v=this;v.vertices=[];v.faces=[];for(var z,m=g.length,C=p.length,n=u.length,k=0;k0;){if(A){if(A.equals(j[k])){A=null;continue}}else A=j[k];o=m*2+k;p=o-1;e(o,p,p+n,o+n);for(t=0;t0;){if(A){if(A.equals(j[k])){A=null;continue}}else A=j[k];for(t=0;t0&&j.push({shape:f,holes:e}),f=t,e=[]):e.push(t):this.Triangulate.area(t)<0?(j.push({shape:t,holes:e}),e=[]):e.push(t);o++}n&&j.push({shape:f,holes:e})}var p,u,v,z,C,A;g=[];for(k=0;k=0?u-1:f.length-1;var t=p-1>=0?p-1:o.length-1,I=[];I.push(o[p]);I.push(f[u]);I.push(f[d]);v=this.Triangulate.area(I);var y=[];y.push(o[p]);y.push(o[t]);y.push(f[u]);C=this.Triangulate.area(y);z=u;A=p;u+=1;p+=-1;u<0&&(u+=f.length);u%=f.length;p<0&&(p+=o.length);p%=f.length;d=u-1>=0?u-1:f.length-1;t=p-1>=0?p-1:o.length- +1;I=[];I.push(o[p]);I.push(f[u]);I.push(f[d]);I=this.Triangulate.area(I);y=[];y.push(o[p]);y.push(o[t]);y.push(f[u]);y=this.Triangulate.area(y);v+C>I+y&&(u=z,p=A,u<0&&(u+=f.length),u%=f.length,p<0&&(p+=o.length),p%=f.length,d=u-1>=0?u-1:f.length-1,t=p-1>=0?p-1:o.length-1);v=f.slice(0,u);C=f.slice(u);z=o.slice(p);A=o.slice(0,p);g.push(o[p]);g.push(f[u]);g.push(f[d]);g.push(o[p]);g.push(o[t]);g.push(f[u]);f=v.concat(z).concat(A).concat(C)}m.shape=f}b=[];p=[];for(k=n=0;k=0;){if(o){if(o.equals(d[b])){o=null;m=this.Triangulate.area(e)>0;j.push(m);g.push(k.divideScalar(e.length));e=[];k=new THREE.Vector2;continue}}else o=d[b];k.addSelf(d[b]);e.push(d[b])}b=d.length;e=0;for(var n;--b>=0;)m=d[b],k=g[e],m=m.clone().subSelf(k),n=this.bezelSize/m.length(), +j[e]?n+=1:n=1-n,n=m.multiplyScalar(n).addSelf(k),f.unshift(n),o?o.equals(d[b])&&(o=null,e++):o=d[b];c.bezel=f;return c},b2p0:function(b,c){var d=1-b;return d*d*c},b2p1:function(b,c){return 2*(1-b)*b*c},b2p2:function(b,c){return b*b*c},b2:function(b,c,d,e){return this.b2p0(b,c)+this.b2p1(b,d)+this.b2p2(b,e)},b3p0:function(b,c){var d=1-b;return d*d*d*c},b3p1:function(b,c){var d=1-b;return 3*d*d*b*c},b3p2:function(b,c){return 3*(1-b)*b*b*c},b3p3:function(b,c){return b*b*b*c},b3:function(b,c,d,e,f){return this.b3p0(b, +c)+this.b3p1(b,d)+this.b3p2(b,e)+this.b3p3(b,f)},extractGlyphPoints:function(b,c,d,e){var f=[],g,j,k,m,o,n,t,p,u,v,z=c.glyphs[b]||c.glyphs[ctxt.options.fallbackCharacter];if(z){if(z.o){c=z._cachedOutline||(z._cachedOutline=z.o.split(" "));k=c.length;for(b=0;b0)for(o=0;o2;){if(t--<=0){console.log("Warning, unable to triangulate polygon!");if(e)return k;return g}m=o;f<=m&&(m=0);o=m+1;f<=o&&(o=0);n=o+1;f<=n&&(n=0);var p;a:{p=b;var u=m,v=o,z=n,C=f,A=j,I=void 0,y=void 0,G=void 0, +F=void 0,B=void 0,M=void 0,L=void 0,O=void 0,w=void 0,y=p[A[u]].x,G=p[A[u]].y,F=p[A[v]].x,B=p[A[v]].y,M=p[A[z]].x,L=p[A[z]].y;if(1.0E-10>(F-y)*(L-G)-(B-G)*(M-y))p=!1;else{for(I=0;I=0&&T>=0&&R>=0){p=!1;break a}}p=!0}}if(p){t= +j[m];p=j[o];u=j[n];g.push(b[t]);g.push(b[p]);g.push(b[u]);k.push([j[m],j[o],j[n]]);m=o;for(n=o+1;n>7)-127;e|=(g&127)<<16|f<<8;if(e==0&&j==-127)return 0;return(1-2*(h>>7))*(1+e*Math.pow(2,-23))*Math.pow(2,j)}function f(b,c){var d=n(b,c),e=n(b,c+1),g=n(b,c+2);return(n(b,c+3)<<24)+(g<<16)+(e<<8)+d}function m(b,c){var d=n(b,c);return(n(b,c+1)<<8)+d}function o(b,c){var d=n(b,c);return d>127?d-256:d}function n(b, +c){return b.charCodeAt(c)&255}function t(c){var d,e,g;d=f(b,c);e=f(b,c+B);g=f(b,c+M);c=m(b,c+L);THREE.BinaryLoader.prototype.f3(A,d,e,g,c)}function p(c){var d,e,g,h,j,n;d=f(b,c);e=f(b,c+B);g=f(b,c+M);h=m(b,c+L);j=f(b,c+O);n=f(b,c+w);c=f(b,c+W);THREE.BinaryLoader.prototype.f3n(A,G,d,e,g,h,j,n,c)}function u(c){var d,e,g,j;d=f(b,c);e=f(b,c+S);g=f(b,c+T);j=f(b,c+h);c=m(b,c+R);THREE.BinaryLoader.prototype.f4(A,d,e,g,j,c)}function v(c){var d,e,g,j,n,o,p,t;d=f(b,c);e=f(b,c+S);g=f(b,c+T);j=f(b,c+h);n=m(b, +c+R);o=f(b,c+J);p=f(b,c+P);t=f(b,c+Q);c=f(b,c+N);THREE.BinaryLoader.prototype.f4n(A,G,d,e,g,j,n,o,p,t,c)}function z(c){var d,e;d=f(b,c);e=f(b,c+Y);c=f(b,c+V);THREE.BinaryLoader.prototype.uv3(A.faceVertexUvs[0],F[d*2],F[d*2+1],F[e*2],F[e*2+1],F[c*2],F[c*2+1])}function C(c){var d,e,g;d=f(b,c);e=f(b,c+Z);g=f(b,c+U);c=f(b,c+ea);THREE.BinaryLoader.prototype.uv4(A.faceVertexUvs[0],F[d*2],F[d*2+1],F[e*2],F[e*2+1],F[g*2],F[g*2+1],F[c*2],F[c*2+1])}var A=this,I=0,y,G=[],F=[],B,M,L,O,w,W,S,T,h,R,J,P,Q,N,Y,V, +Z,U,ea,ia,D,H,$,ca,aa;THREE.Geometry.call(this);THREE.Loader.prototype.init_materials(A,e,c);y={signature:b.substr(I,8),header_bytes:n(b,I+8),vertex_coordinate_bytes:n(b,I+9),normal_coordinate_bytes:n(b,I+10),uv_coordinate_bytes:n(b,I+11),vertex_index_bytes:n(b,I+12),normal_index_bytes:n(b,I+13),uv_index_bytes:n(b,I+14),material_index_bytes:n(b,I+15),nvertices:f(b,I+16),nnormals:f(b,I+16+4),nuvs:f(b,I+16+8),ntri_flat:f(b,I+16+12),ntri_smooth:f(b,I+16+16),ntri_flat_uv:f(b,I+16+20),ntri_smooth_uv:f(b, +I+16+24),nquad_flat:f(b,I+16+28),nquad_smooth:f(b,I+16+32),nquad_flat_uv:f(b,I+16+36),nquad_smooth_uv:f(b,I+16+40)};I+=y.header_bytes;B=y.vertex_index_bytes;M=y.vertex_index_bytes*2;L=y.vertex_index_bytes*3;O=y.vertex_index_bytes*3+y.material_index_bytes;w=y.vertex_index_bytes*3+y.material_index_bytes+y.normal_index_bytes;W=y.vertex_index_bytes*3+y.material_index_bytes+y.normal_index_bytes*2;S=y.vertex_index_bytes;T=y.vertex_index_bytes*2;h=y.vertex_index_bytes*3;R=y.vertex_index_bytes*4;J=y.vertex_index_bytes* +4+y.material_index_bytes;P=y.vertex_index_bytes*4+y.material_index_bytes+y.normal_index_bytes;Q=y.vertex_index_bytes*4+y.material_index_bytes+y.normal_index_bytes*2;N=y.vertex_index_bytes*4+y.material_index_bytes+y.normal_index_bytes*3;Y=y.uv_index_bytes;V=y.uv_index_bytes*2;Z=y.uv_index_bytes;U=y.uv_index_bytes*2;ea=y.uv_index_bytes*3;c=y.vertex_index_bytes*3+y.material_index_bytes;aa=y.vertex_index_bytes*4+y.material_index_bytes;ia=y.ntri_flat*c;D=y.ntri_smooth*(c+y.normal_index_bytes*3);H=y.ntri_flat_uv* +(c+y.uv_index_bytes*3);$=y.ntri_smooth_uv*(c+y.normal_index_bytes*3+y.uv_index_bytes*3);ca=y.nquad_flat*aa;c=y.nquad_smooth*(aa+y.normal_index_bytes*4);aa=y.nquad_flat_uv*(aa+y.uv_index_bytes*4);I+=function(c){for(var e,f,g,h=y.vertex_coordinate_bytes*3,k=c+y.nvertices*h;c1&&(O=[new THREE.MeshFaceMaterial]);object=new THREE.Mesh(B,O);object.name=u;object.position.set(y[0],y[1],y[2]);q?(object.quaternion.set(q[0],q[1],q[2],q[3]),object.useQuaternion=!0):object.rotation.set(r[0],r[1],r[2]);object.scale.set(s[0],s[1],s[2]);object.visible=I.visible;J.scene.addObject(object);J.objects[u]=object;if(I.meshCollider){var b=THREE.CollisionUtils.MeshColliderWBox(object);J.scene.collisions.colliders.push(b)}if(I.castsShadow)b=new THREE.ShadowVolume(B),J.scene.addChild(b), +b.position=object.position,b.rotation=object.rotation,b.scale=object.scale;I.trigger&&I.trigger.toLowerCase()!="none"&&(b={type:I.trigger,object:I},J.triggers[object.name]=b)}}else y=I.position,r=I.rotation,q=I.quaternion,s=I.scale,q=0,object=new THREE.Object3D,object.name=u,object.position.set(y[0],y[1],y[2]),q?(object.quaternion.set(q[0],q[1],q[2],q[3]),object.useQuaternion=!0):object.rotation.set(r[0],r[1],r[2]),object.scale.set(s[0],s[1],s[2]),object.visible=I.visible!==void 0?I.visible:!1,J.scene.addObject(object), +J.objects[u]=object,J.empties[u]=object,I.trigger&&I.trigger.toLowerCase()!="none"&&(b={type:I.trigger,object:I},J.triggers[object.name]=b)}function m(b){return function(c){J.geometries[b]=c;k();S-=1;d.onLoadComplete();n()}}function o(b){return function(c){J.geometries[b]=c}}function n(){d.callbackProgress({totalModels:h,totalTextures:R,loadedModels:h-S,loadedTextures:R-T},J);d.onLoadProgress();S==0&&T==0&&c(J)}var t,p,u,v,z,C,A,I,y,G,F,B,M,L,O,w,W,S,T,h,R,J;w=b.data;b=new THREE.BinaryLoader;W=new THREE.JSONLoader; +T=S=0;J={scene:new THREE.Scene,geometries:{},materials:{},textures:{},objects:{},cameras:{},lights:{},fogs:{},triggers:{},empties:{}};var P=!1;for(u in w.objects)if(I=w.objects[u],I.meshCollider){P=!0;break}if(P)J.scene.collisions=new THREE.CollisionSystem;if(w.transform){P=w.transform.position;G=w.transform.rotation;var Q=w.transform.scale;P&&J.scene.position.set(P[0],P[1],P[2]);G&&J.scene.rotation.set(G[0],G[1],G[2]);Q&&J.scene.scale.set(Q[0],Q[1],Q[2]);(P||G||Q)&&J.scene.updateMatrix()}P=function(){T-= +1;n();d.onLoadComplete()};for(z in w.cameras){G=w.cameras[z];if(G.type=="perspective")M=new THREE.Camera(G.fov,G.aspect,G.near,G.far);else if(G.type=="ortho")M=new THREE.Camera,M.projectionMatrix=THREE.Matrix4.makeOrtho(G.left,G.right,G.top,G.bottom,G.near,G.far);y=G.position;G=G.target;M.position.set(y[0],y[1],y[2]);M.target.position.set(G[0],G[1],G[2]);J.cameras[z]=M}for(v in w.lights){z=w.lights[v];M=z.color!==void 0?z.color:16777215;G=z.intensity!==void 0?z.intensity:1;if(z.type=="directional")y= +z.direction,light=new THREE.DirectionalLight(M,G),light.position.set(y[0],y[1],y[2]),light.position.normalize();else if(z.type=="point")y=z.position,light=new THREE.PointLight(M,G),light.position.set(y[0],y[1],y[2]);J.scene.addLight(light);J.lights[v]=light}for(C in w.fogs)v=w.fogs[C],v.type=="linear"?L=new THREE.Fog(0,v.near,v.far):v.type=="exp2"&&(L=new THREE.FogExp2(0,v.density)),G=v.color,L.color.setRGB(G[0],G[1],G[2]),J.fogs[C]=L;if(J.cameras&&w.defaults.camera)J.currentCamera=J.cameras[w.defaults.camera]; +if(J.fogs&&w.defaults.fog)J.scene.fog=J.fogs[w.defaults.fog];G=w.defaults.bgcolor;J.bgColor=new THREE.Color;J.bgColor.setRGB(G[0],G[1],G[2]);J.bgColorAlpha=w.defaults.bgalpha;for(t in w.geometries)if(C=w.geometries[t],C.type=="bin_mesh"||C.type=="ascii_mesh")S+=1,d.onLoadStart();h=S;for(t in w.geometries)C=w.geometries[t],C.type=="cube"?(B=new THREE.CubeGeometry(C.width,C.height,C.depth,C.segmentsWidth,C.segmentsHeight,C.segmentsDepth,null,C.flipped,C.sides),J.geometries[t]=B):C.type=="plane"?(B= +new THREE.PlaneGeometry(C.width,C.height,C.segmentsWidth,C.segmentsHeight),J.geometries[t]=B):C.type=="sphere"?(B=new THREE.SphereGeometry(C.radius,C.segmentsWidth,C.segmentsHeight),J.geometries[t]=B):C.type=="cylinder"?(B=new THREE.CylinderGeometry(C.numSegs,C.topRad,C.botRad,C.height,C.topOffset,C.botOffset),J.geometries[t]=B):C.type=="torus"?(B=new THREE.TorusGeometry(C.radius,C.tube,C.segmentsR,C.segmentsT),J.geometries[t]=B):C.type=="icosahedron"?(B=new THREE.IcosahedronGeometry(C.subdivisions), +J.geometries[t]=B):C.type=="bin_mesh"?b.load({model:e(C.url,w.urlBaseType),callback:m(t)}):C.type=="ascii_mesh"?W.load({model:e(C.url,w.urlBaseType),callback:m(t)}):C.type=="embedded_mesh"&&(C=w.embeds[C.id])&&W.createModel(C,o(t),"");for(A in w.textures)if(t=w.textures[A],t.url instanceof Array){T+=t.url.length;for(b=0;b=this.maxCount-3&&k(this)};this.begin=function(){this.count=0; +this.hasNormal=this.hasPos=!1};this.end=function(b){if(this.count!=0){for(var c=this.count*3;cthis.size-1&&(m=this.size-1);var p=Math.floor(o-k);p<1&&(p=1);o=Math.floor(o+k);o>this.size-1&&(o=this.size-1);var u=Math.floor(n-k);u<1&&(u=1);k=Math.floor(n+k);k>this.size-1&&(k=this.size- +1);for(var v,z,C,A,I,y;t0&&(this.field[C+v]+=A)}}};this.addPlaneX=function(b,c){var f,g,j,k,m,o=this.size,n=this.yd,t=this.zd,p=this.field,u=o*Math.sqrt(b/c);u>o&&(u=o);for(f=0;f0)for(g=0;gn&&(v=n);for(g=0;g0){m=g*t;for(f=0;fsize&&(dist=size);for(j=0;j0){m=zd*j;for(g=0;gg?this.hits.push(f):this.hits.unshift(f),g=e;return this.hits}; +THREE.CollisionSystem.prototype.rayCastNearest=function(b){var c=this.rayCastAll(b);if(c.length==0)return null;for(var d=0;c[d]instanceof THREE.MeshCollider;){var e=this.rayMesh(b,c[d]);if(e.distc.length)return null;return c[d]}; +THREE.CollisionSystem.prototype.rayCast=function(b,c){if(c instanceof THREE.PlaneCollider)return this.rayPlane(b,c);else if(c instanceof THREE.SphereCollider)return this.raySphere(b,c);else if(c instanceof THREE.BoxCollider)return this.rayBox(b,c);else if(c instanceof THREE.MeshCollider&&c.box)return this.rayBox(b,c.box)}; +THREE.CollisionSystem.prototype.rayMesh=function(b,c){for(var d=this.makeRayLocal(b,c.mesh),e=Number.MAX_VALUE,f,g=0;g=k*f))return Number.MAX_VALUE;j/=k;k=THREE.CollisionSystem.__v3;k.copy(b.direction);k.multiplyScalar(j);k.addSelf(b.origin);Math.abs(g.x)>Math.abs(g.y)?Math.abs(g.x)>Math.abs(g.z)?(b=k.y-c.y,g=d.y-c.y, +f=e.y-c.y,k=k.z-c.z,d=d.z-c.z,e=e.z-c.z):(b=k.x-c.x,g=d.x-c.x,f=e.x-c.x,k=k.y-c.y,d=d.y-c.y,e=e.y-c.y):Math.abs(g.y)>Math.abs(g.z)?(b=k.x-c.x,g=d.x-c.x,f=e.x-c.x,k=k.z-c.z,d=d.z-c.z,e=e.z-c.z):(b=k.x-c.x,g=d.x-c.x,f=e.x-c.x,k=k.y-c.y,d=d.y-c.y,e=e.y-c.y);c=g*e-d*f;if(c==0)return Number.MAX_VALUE;c=1/c;e=(b*e-k*f)*c;if(!(e>=0))return Number.MAX_VALUE;c*=g*k-d*b;if(!(c>=0))return Number.MAX_VALUE;if(!(1-e-c>=0))return Number.MAX_VALUE;return j}; +THREE.CollisionSystem.prototype.makeRayLocal=function(b,c){var d=THREE.CollisionSystem.__m;THREE.Matrix4.makeInvert(c.matrixWorld,d);var e=THREE.CollisionSystem.__r;e.origin.copy(b.origin);e.direction.copy(b.direction);d.multiplyVector3(e.origin);d.rotateAxis(e.direction);e.direction.normalize();return e}; +THREE.CollisionSystem.prototype.rayBox=function(b,c){var d;c.dynamic&&c.mesh&&c.mesh.matrixWorld?d=this.makeRayLocal(b,c.mesh):(d=THREE.CollisionSystem.__r,d.origin.copy(b.origin),d.direction.copy(b.direction));var e=0,f=0,g=0,j=0,k=0,m=0,o=!0;d.origin.xc.max.x&&(e=c.max.x-d.origin.x,e/=d.direction.x,o=!1,j=1);d.origin.yc.max.y&&(f=c.max.y-d.origin.y,f/=d.direction.y, +o=!1,k=1);d.origin.zc.max.z&&(g=c.max.z-d.origin.z,g/=d.direction.z,o=!1,m=1);if(o)return-1;o=0;f>e&&(o=1,e=f);g>e&&(o=2,e=g);switch(o){case 0:k=d.origin.y+d.direction.y*e;if(kc.max.y)return Number.MAX_VALUE;d=d.origin.z+d.direction.z*e;if(dc.max.z)return Number.MAX_VALUE;c.normal.set(j,0,0);break;case 1:j=d.origin.x+d.direction.x*e;if(jc.max.x)return Number.MAX_VALUE;d=d.origin.z+d.direction.z* +e;if(dc.max.z)return Number.MAX_VALUE;c.normal.set(0,k,0);break;case 2:j=d.origin.x+d.direction.x*e;if(jc.max.x)return Number.MAX_VALUE;k=d.origin.y+d.direction.y*e;if(kc.max.y)return Number.MAX_VALUE;c.normal.set(0,0,m)}return e};THREE.CollisionSystem.prototype.rayPlane=function(b,c){var d=b.direction.dot(c.normal),e=c.point.dot(c.normal);if(d<0)d=(e-b.origin.dot(c.normal))/d;else return Number.MAX_VALUE;return d>0?d:Number.MAX_VALUE}; +THREE.CollisionSystem.prototype.raySphere=function(b,c){var d=c.center.clone().subSelf(b.origin);if(d.lengthSq=0)return Math.abs(e)-Math.sqrt(d);return Number.MAX_VALUE};THREE.CollisionSystem.__v1=new THREE.Vector3;THREE.CollisionSystem.__v2=new THREE.Vector3;THREE.CollisionSystem.__v3=new THREE.Vector3;THREE.CollisionSystem.__nr=new THREE.Vector3;THREE.CollisionSystem.__m=new THREE.Matrix4; +THREE.CollisionSystem.__r=new THREE.Ray;THREE.CollisionUtils={};THREE.CollisionUtils.MeshOBB=function(b){b.geometry.computeBoundingBox();var c=b.geometry.boundingBox,d=new THREE.Vector3(c.x[0],c.y[0],c.z[0]),c=new THREE.Vector3(c.x[1],c.y[1],c.z[1]),d=new THREE.BoxCollider(d,c);d.mesh=b;return d};THREE.CollisionUtils.MeshAABB=function(b){var c=THREE.CollisionUtils.MeshOBB(b);c.min.addSelf(b.position);c.max.addSelf(b.position);c.dynamic=!1;return c}; +THREE.CollisionUtils.MeshColliderWBox=function(b){return new THREE.MeshCollider(b,THREE.CollisionUtils.MeshOBB(b))}; +if(THREE.WebGLRenderer)THREE.AnaglyphWebGLRenderer=function(b){THREE.WebGLRenderer.call(this,b);var c=this,d=this.setSize,e=this.render,f=new THREE.Camera,g=new THREE.Camera,j=new THREE.Matrix4,k=new THREE.Matrix4,m,o,n;f.useTarget=g.useTarget=!1;f.matrixAutoUpdate=g.matrixAutoUpdate=!1;var b={minFilter:THREE.LinearFilter,magFilter:THREE.NearestFilter,format:THREE.RGBAFormat},t=new THREE.WebGLRenderTarget(512,512,b),p=new THREE.WebGLRenderTarget(512,512,b),u=new THREE.Camera(53,1,1,1E4);u.position.z= +2;_material=new THREE.MeshShaderMaterial({uniforms:{mapLeft:{type:"t",value:0,texture:t},mapRight:{type:"t",value:1,texture:p}},vertexShader:"varying vec2 vUv;\nvoid main() {\nvUv = vec2( uv.x, 1.0 - uv.y );\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D mapLeft;\nuniform sampler2D mapRight;\nvarying vec2 vUv;\nvoid main() {\nvec4 colorL, colorR;\nvec2 uv = vUv;\ncolorL = texture2D( mapLeft, uv );\ncolorR = texture2D( mapRight, uv );\ngl_FragColor = vec4( colorL.g * 0.7 + colorL.b * 0.3, colorR.g, colorR.b, colorL.a + colorR.a ) * 1.1;\n}"}); +var v=new THREE.Scene;v.addObject(new THREE.Mesh(new THREE.PlaneGeometry(2,2),_material));this.setSize=function(b,e){d.call(c,b,e);t.width=b;t.height=e;p.width=b;p.height=e};this.render=function(b,d){d.update(null,!0);if(m!==d.aspect||o!==d.near||n!==d.fov){m=d.aspect;o=d.near;n=d.fov;var A=d.projectionMatrix.clone(),I=125/30*0.5,y=I*o/125,G=o*Math.tan(n*Math.PI/360),F;j.n14=I;k.n14=-I;I=-G*m+y;F=G*m+y;A.n11=2*o/(F-I);A.n13=(F+I)/(F-I);f.projectionMatrix=A.clone();I=-G*m-y;F=G*m-y;A.n11=2*o/(F-I); +A.n13=(F+I)/(F-I);g.projectionMatrix=A.clone()}f.matrix=d.matrixWorld.clone().multiplySelf(k);f.update(null,!0);f.position.copy(d.position);f.near=o;f.far=d.far;e.call(c,b,f,t,!0);g.matrix=d.matrixWorld.clone().multiplySelf(j);g.update(null,!0);g.position.copy(d.position);g.near=o;g.far=d.far;e.call(c,b,g,p,!0);e.call(c,v,u)}}; +if(THREE.WebGLRenderer)THREE.CrosseyedWebGLRenderer=function(b){THREE.WebGLRenderer.call(this,b);this.autoClear=!1;var c=this,d=this.setSize,e=this.render,f,g,j=new THREE.Camera,k=new THREE.Camera;c.separation=10;if(b&&b.separation!==void 0)c.separation=b.separation;(new THREE.Camera(53,window.innerWidth/2/window.innerHeight,1,1E4)).position.z=-10;this.setSize=function(b,e){d.call(c,b,e);f=b/2;g=e};this.render=function(b,d){this.clear();j.fov=d.fov;j.aspect=0.5*d.aspect;j.near=d.near;j.far=d.far; +j.updateProjectionMatrix();j.position.copy(d.position);j.target.position.copy(d.target.position);j.translateX(c.separation);k.projectionMatrix=j.projectionMatrix;k.position.copy(d.position);k.target.position.copy(d.target.position);k.translateX(-c.separation);this.setViewport(0,0,f,g);e.call(c,b,j);this.setViewport(f,0,f,g);e.call(c,b,k,!1)}}; diff --git a/build/custom/ThreeWebGL.js b/build/custom/ThreeWebGL.js index 05b8be13efc79d7d8c05151576e6e26882bd9ab3..27266def5fb93f861dc1c1c076580ae2bc297711 100644 --- a/build/custom/ThreeWebGL.js +++ b/build/custom/ThreeWebGL.js @@ -24,18 +24,18 @@ THREE.Matrix3.prototype={transpose:function(){var b,e=this.m;b=e[1];e[1]=e[3];e[ THREE.Matrix4.prototype={set:function(b,e,d,f,h,i,g,j,k,o,p,n,q,w,y,D){this.n11=b;this.n12=e;this.n13=d;this.n14=f;this.n21=h;this.n22=i;this.n23=g;this.n24=j;this.n31=k;this.n32=o;this.n33=p;this.n34=n;this.n41=q;this.n42=w;this.n43=y;this.n44=D;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(b){this.set(b.n11,b.n12,b.n13,b.n14,b.n21,b.n22,b.n23,b.n24,b.n31,b.n32,b.n33,b.n34,b.n41,b.n42,b.n43,b.n44);return this},lookAt:function(b,e,d){var f=THREE.Matrix4.__v1, h=THREE.Matrix4.__v2,i=THREE.Matrix4.__v3;i.sub(b,e).normalize();if(i.length()===0)i.z=1;f.cross(d,i).normalize();f.length()===0&&(i.x+=1.0E-4,f.cross(d,i).normalize());h.cross(i,f).normalize();this.n11=f.x;this.n12=h.x;this.n13=i.x;this.n21=f.y;this.n22=h.y;this.n23=i.y;this.n31=f.z;this.n32=h.z;this.n33=i.z;return this},multiplyVector3:function(b){var e=b.x,d=b.y,f=b.z,h=1/(this.n41*e+this.n42*d+this.n43*f+this.n44);b.x=(this.n11*e+this.n12*d+this.n13*f+this.n14)*h;b.y=(this.n21*e+this.n22*d+this.n23* f+this.n24)*h;b.z=(this.n31*e+this.n32*d+this.n33*f+this.n34)*h;return b},multiplyVector4:function(b){var e=b.x,d=b.y,f=b.z,h=b.w;b.x=this.n11*e+this.n12*d+this.n13*f+this.n14*h;b.y=this.n21*e+this.n22*d+this.n23*f+this.n24*h;b.z=this.n31*e+this.n32*d+this.n33*f+this.n34*h;b.w=this.n41*e+this.n42*d+this.n43*f+this.n44*h;return b},rotateAxis:function(b){var e=b.x,d=b.y,f=b.z;b.x=e*this.n11+d*this.n12+f*this.n13;b.y=e*this.n21+d*this.n22+f*this.n23;b.z=e*this.n31+d*this.n32+f*this.n33;b.normalize(); -return b},crossVector:function(b){var e=new THREE.Vector4;e.x=this.n11*b.x+this.n12*b.y+this.n13*b.z+this.n14*b.w;e.y=this.n21*b.x+this.n22*b.y+this.n23*b.z+this.n24*b.w;e.z=this.n31*b.x+this.n32*b.y+this.n33*b.z+this.n34*b.w;e.w=b.w?this.n41*b.x+this.n42*b.y+this.n43*b.z+this.n44*b.w:1;return e},multiply:function(b,e){var d=b.n11,f=b.n12,h=b.n13,i=b.n14,g=b.n21,j=b.n22,k=b.n23,o=b.n24,p=b.n31,n=b.n32,q=b.n33,w=b.n34,y=b.n41,D=b.n42,z=b.n43,C=b.n44,ga=e.n11,M=e.n12,O=e.n13,F=e.n14,v=e.n21,$=e.n22, -B=e.n23,aa=e.n24,K=e.n31,na=e.n32,U=e.n33,R=e.n34,c=e.n41,ha=e.n42,S=e.n43,ka=e.n44;this.n11=d*ga+f*v+h*K+i*c;this.n12=d*M+f*$+h*na+i*ha;this.n13=d*O+f*B+h*U+i*S;this.n14=d*F+f*aa+h*R+i*ka;this.n21=g*ga+j*v+k*K+o*c;this.n22=g*M+j*$+k*na+o*ha;this.n23=g*O+j*B+k*U+o*S;this.n24=g*F+j*aa+k*R+o*ka;this.n31=p*ga+n*v+q*K+w*c;this.n32=p*M+n*$+q*na+w*ha;this.n33=p*O+n*B+q*U+w*S;this.n34=p*F+n*aa+q*R+w*ka;this.n41=y*ga+D*v+z*K+C*c;this.n42=y*M+D*$+z*na+C*ha;this.n43=y*O+D*B+z*U+C*S;this.n44=y*F+D*aa+z*R+C* -ka;return this},multiplyToArray:function(b,e,d){this.multiply(b,e);d[0]=this.n11;d[1]=this.n21;d[2]=this.n31;d[3]=this.n41;d[4]=this.n12;d[5]=this.n22;d[6]=this.n32;d[7]=this.n42;d[8]=this.n13;d[9]=this.n23;d[10]=this.n33;d[11]=this.n43;d[12]=this.n14;d[13]=this.n24;d[14]=this.n34;d[15]=this.n44;return this},multiplySelf:function(b){this.multiply(this,b);return this},multiplyScalar:function(b){this.n11*=b;this.n12*=b;this.n13*=b;this.n14*=b;this.n21*=b;this.n22*=b;this.n23*=b;this.n24*=b;this.n31*= -b;this.n32*=b;this.n33*=b;this.n34*=b;this.n41*=b;this.n42*=b;this.n43*=b;this.n44*=b;return this},determinant:function(){var b=this.n11,e=this.n12,d=this.n13,f=this.n14,h=this.n21,i=this.n22,g=this.n23,j=this.n24,k=this.n31,o=this.n32,p=this.n33,n=this.n34,q=this.n41,w=this.n42,y=this.n43,D=this.n44;return f*g*o*q-d*j*o*q-f*i*p*q+e*j*p*q+d*i*n*q-e*g*n*q-f*g*k*w+d*j*k*w+f*h*p*w-b*j*p*w-d*h*n*w+b*g*n*w+f*i*k*y-e*j*k*y-f*h*o*y+b*j*o*y+e*h*n*y-b*i*n*y-d*i*k*D+e*g*k*D+d*h*o*D-b*g*o*D-e*h*p*D+b*i*p*D}, -transpose:function(){var b;b=this.n21;this.n21=this.n12;this.n12=b;b=this.n31;this.n31=this.n13;this.n13=b;b=this.n32;this.n32=this.n23;this.n23=b;b=this.n41;this.n41=this.n14;this.n14=b;b=this.n42;this.n42=this.n24;this.n24=b;b=this.n43;this.n43=this.n34;this.n43=b;return this},clone:function(){var b=new THREE.Matrix4;b.n11=this.n11;b.n12=this.n12;b.n13=this.n13;b.n14=this.n14;b.n21=this.n21;b.n22=this.n22;b.n23=this.n23;b.n24=this.n24;b.n31=this.n31;b.n32=this.n32;b.n33=this.n33;b.n34=this.n34; -b.n41=this.n41;b.n42=this.n42;b.n43=this.n43;b.n44=this.n44;return b},flatten:function(){this.flat[0]=this.n11;this.flat[1]=this.n21;this.flat[2]=this.n31;this.flat[3]=this.n41;this.flat[4]=this.n12;this.flat[5]=this.n22;this.flat[6]=this.n32;this.flat[7]=this.n42;this.flat[8]=this.n13;this.flat[9]=this.n23;this.flat[10]=this.n33;this.flat[11]=this.n43;this.flat[12]=this.n14;this.flat[13]=this.n24;this.flat[14]=this.n34;this.flat[15]=this.n44;return this.flat},flattenToArray:function(b){b[0]=this.n11; -b[1]=this.n21;b[2]=this.n31;b[3]=this.n41;b[4]=this.n12;b[5]=this.n22;b[6]=this.n32;b[7]=this.n42;b[8]=this.n13;b[9]=this.n23;b[10]=this.n33;b[11]=this.n43;b[12]=this.n14;b[13]=this.n24;b[14]=this.n34;b[15]=this.n44;return b},flattenToArrayOffset:function(b,e){b[e]=this.n11;b[e+1]=this.n21;b[e+2]=this.n31;b[e+3]=this.n41;b[e+4]=this.n12;b[e+5]=this.n22;b[e+6]=this.n32;b[e+7]=this.n42;b[e+8]=this.n13;b[e+9]=this.n23;b[e+10]=this.n33;b[e+11]=this.n43;b[e+12]=this.n14;b[e+13]=this.n24;b[e+14]=this.n34; -b[e+15]=this.n44;return b},setTranslation:function(b,e,d){this.set(1,0,0,b,0,1,0,e,0,0,1,d,0,0,0,1);return this},setScale:function(b,e,d){this.set(b,0,0,0,0,e,0,0,0,0,d,0,0,0,0,1);return this},setRotationX:function(b){var e=Math.cos(b),b=Math.sin(b);this.set(1,0,0,0,0,e,-b,0,0,b,e,0,0,0,0,1);return this},setRotationY:function(b){var e=Math.cos(b),b=Math.sin(b);this.set(e,0,b,0,0,1,0,0,-b,0,e,0,0,0,0,1);return this},setRotationZ:function(b){var e=Math.cos(b),b=Math.sin(b);this.set(e,-b,0,0,b,e,0,0, -0,0,1,0,0,0,0,1);return this},setRotationAxis:function(b,e){var d=Math.cos(e),f=Math.sin(e),h=1-d,i=b.x,g=b.y,j=b.z,k=h*i,o=h*g;this.set(k*i+d,k*g-f*j,k*j+f*g,0,k*g+f*j,o*g+d,o*j-f*i,0,k*j-f*g,o*j+f*i,h*j*j+d,0,0,0,0,1);return this},setPosition:function(b){this.n14=b.x;this.n24=b.y;this.n34=b.z;return this},getPosition:function(){if(!this.position)this.position=new THREE.Vector3;this.position.set(this.n14,this.n24,this.n34);return this.position},getColumnX:function(){if(!this.columnX)this.columnX= -new THREE.Vector3;this.columnX.set(this.n11,this.n21,this.n31);return this.columnX},getColumnY:function(){if(!this.columnY)this.columnY=new THREE.Vector3;this.columnY.set(this.n12,this.n22,this.n32);return this.columnY},getColumnZ:function(){if(!this.columnZ)this.columnZ=new THREE.Vector3;this.columnZ.set(this.n13,this.n23,this.n33);return this.columnZ},setRotationFromEuler:function(b,e){var d=b.x,f=b.y,h=b.z,i=Math.cos(d),d=Math.sin(d),g=Math.cos(f),f=Math.sin(f),j=Math.cos(h),h=Math.sin(h);switch(e){case "YXZ":var k= -g*j,o=g*h,p=f*j,n=f*h;this.n11=k+n*d;this.n12=p*d-o;this.n13=i*f;this.n21=i*h;this.n22=i*j;this.n23=-d;this.n31=o*d-p;this.n32=n+k*d;this.n33=i*g;break;case "ZXY":k=g*j;o=g*h;p=f*j;n=f*h;this.n11=k-n*d;this.n12=-i*h;this.n13=p+o*d;this.n21=o+p*d;this.n22=i*j;this.n23=n-k*d;this.n31=-i*f;this.n32=d;this.n33=i*g;break;case "ZYX":k=i*j;o=i*h;p=d*j;n=d*h;this.n11=g*j;this.n12=p*f-o;this.n13=k*f+n;this.n21=g*h;this.n22=n*f+k;this.n23=o*f-p;this.n31=-f;this.n32=d*g;this.n33=i*g;break;case "YZX":k=i*g;o= -i*f;p=d*g;n=d*f;this.n11=g*j;this.n12=n-k*h;this.n13=p*h+o;this.n21=h;this.n22=i*j;this.n23=-d*j;this.n31=-f*j;this.n32=o*h+p;this.n33=k-n*h;break;case "XZY":k=i*g;o=i*f;p=d*g;n=d*f;this.n11=g*j;this.n12=-h;this.n13=f*j;this.n21=k*h+n;this.n22=i*j;this.n23=o*h-p;this.n31=p*h-o;this.n32=d*j;this.n33=n*h+k;break;default:k=i*j,o=i*h,p=d*j,n=d*h,this.n11=g*j,this.n12=-g*h,this.n13=f,this.n21=o+p*f,this.n22=k-n*f,this.n23=-d*g,this.n31=n-k*f,this.n32=p+o*f,this.n33=i*g}return this},setRotationFromQuaternion:function(b){var e= +return b},crossVector:function(b){var e=new THREE.Vector4;e.x=this.n11*b.x+this.n12*b.y+this.n13*b.z+this.n14*b.w;e.y=this.n21*b.x+this.n22*b.y+this.n23*b.z+this.n24*b.w;e.z=this.n31*b.x+this.n32*b.y+this.n33*b.z+this.n34*b.w;e.w=b.w?this.n41*b.x+this.n42*b.y+this.n43*b.z+this.n44*b.w:1;return e},multiply:function(b,e){var d=b.n11,f=b.n12,h=b.n13,i=b.n14,g=b.n21,j=b.n22,k=b.n23,o=b.n24,p=b.n31,n=b.n32,q=b.n33,w=b.n34,y=b.n41,D=b.n42,z=b.n43,C=b.n44,ga=e.n11,aa=e.n12,O=e.n13,F=e.n14,v=e.n21,M=e.n22, +B=e.n23,$=e.n24,K=e.n31,na=e.n32,U=e.n33,R=e.n34,c=e.n41,ha=e.n42,S=e.n43,ka=e.n44;this.n11=d*ga+f*v+h*K+i*c;this.n12=d*aa+f*M+h*na+i*ha;this.n13=d*O+f*B+h*U+i*S;this.n14=d*F+f*$+h*R+i*ka;this.n21=g*ga+j*v+k*K+o*c;this.n22=g*aa+j*M+k*na+o*ha;this.n23=g*O+j*B+k*U+o*S;this.n24=g*F+j*$+k*R+o*ka;this.n31=p*ga+n*v+q*K+w*c;this.n32=p*aa+n*M+q*na+w*ha;this.n33=p*O+n*B+q*U+w*S;this.n34=p*F+n*$+q*R+w*ka;this.n41=y*ga+D*v+z*K+C*c;this.n42=y*aa+D*M+z*na+C*ha;this.n43=y*O+D*B+z*U+C*S;this.n44=y*F+D*$+z*R+C*ka; +return this},multiplyToArray:function(b,e,d){this.multiply(b,e);d[0]=this.n11;d[1]=this.n21;d[2]=this.n31;d[3]=this.n41;d[4]=this.n12;d[5]=this.n22;d[6]=this.n32;d[7]=this.n42;d[8]=this.n13;d[9]=this.n23;d[10]=this.n33;d[11]=this.n43;d[12]=this.n14;d[13]=this.n24;d[14]=this.n34;d[15]=this.n44;return this},multiplySelf:function(b){this.multiply(this,b);return this},multiplyScalar:function(b){this.n11*=b;this.n12*=b;this.n13*=b;this.n14*=b;this.n21*=b;this.n22*=b;this.n23*=b;this.n24*=b;this.n31*=b; +this.n32*=b;this.n33*=b;this.n34*=b;this.n41*=b;this.n42*=b;this.n43*=b;this.n44*=b;return this},determinant:function(){var b=this.n11,e=this.n12,d=this.n13,f=this.n14,h=this.n21,i=this.n22,g=this.n23,j=this.n24,k=this.n31,o=this.n32,p=this.n33,n=this.n34,q=this.n41,w=this.n42,y=this.n43,D=this.n44;return f*g*o*q-d*j*o*q-f*i*p*q+e*j*p*q+d*i*n*q-e*g*n*q-f*g*k*w+d*j*k*w+f*h*p*w-b*j*p*w-d*h*n*w+b*g*n*w+f*i*k*y-e*j*k*y-f*h*o*y+b*j*o*y+e*h*n*y-b*i*n*y-d*i*k*D+e*g*k*D+d*h*o*D-b*g*o*D-e*h*p*D+b*i*p*D},transpose:function(){var b; +b=this.n21;this.n21=this.n12;this.n12=b;b=this.n31;this.n31=this.n13;this.n13=b;b=this.n32;this.n32=this.n23;this.n23=b;b=this.n41;this.n41=this.n14;this.n14=b;b=this.n42;this.n42=this.n24;this.n24=b;b=this.n43;this.n43=this.n34;this.n43=b;return this},clone:function(){var b=new THREE.Matrix4;b.n11=this.n11;b.n12=this.n12;b.n13=this.n13;b.n14=this.n14;b.n21=this.n21;b.n22=this.n22;b.n23=this.n23;b.n24=this.n24;b.n31=this.n31;b.n32=this.n32;b.n33=this.n33;b.n34=this.n34;b.n41=this.n41;b.n42=this.n42; +b.n43=this.n43;b.n44=this.n44;return b},flatten:function(){this.flat[0]=this.n11;this.flat[1]=this.n21;this.flat[2]=this.n31;this.flat[3]=this.n41;this.flat[4]=this.n12;this.flat[5]=this.n22;this.flat[6]=this.n32;this.flat[7]=this.n42;this.flat[8]=this.n13;this.flat[9]=this.n23;this.flat[10]=this.n33;this.flat[11]=this.n43;this.flat[12]=this.n14;this.flat[13]=this.n24;this.flat[14]=this.n34;this.flat[15]=this.n44;return this.flat},flattenToArray:function(b){b[0]=this.n11;b[1]=this.n21;b[2]=this.n31; +b[3]=this.n41;b[4]=this.n12;b[5]=this.n22;b[6]=this.n32;b[7]=this.n42;b[8]=this.n13;b[9]=this.n23;b[10]=this.n33;b[11]=this.n43;b[12]=this.n14;b[13]=this.n24;b[14]=this.n34;b[15]=this.n44;return b},flattenToArrayOffset:function(b,e){b[e]=this.n11;b[e+1]=this.n21;b[e+2]=this.n31;b[e+3]=this.n41;b[e+4]=this.n12;b[e+5]=this.n22;b[e+6]=this.n32;b[e+7]=this.n42;b[e+8]=this.n13;b[e+9]=this.n23;b[e+10]=this.n33;b[e+11]=this.n43;b[e+12]=this.n14;b[e+13]=this.n24;b[e+14]=this.n34;b[e+15]=this.n44;return b}, +setTranslation:function(b,e,d){this.set(1,0,0,b,0,1,0,e,0,0,1,d,0,0,0,1);return this},setScale:function(b,e,d){this.set(b,0,0,0,0,e,0,0,0,0,d,0,0,0,0,1);return this},setRotationX:function(b){var e=Math.cos(b),b=Math.sin(b);this.set(1,0,0,0,0,e,-b,0,0,b,e,0,0,0,0,1);return this},setRotationY:function(b){var e=Math.cos(b),b=Math.sin(b);this.set(e,0,b,0,0,1,0,0,-b,0,e,0,0,0,0,1);return this},setRotationZ:function(b){var e=Math.cos(b),b=Math.sin(b);this.set(e,-b,0,0,b,e,0,0,0,0,1,0,0,0,0,1);return this}, +setRotationAxis:function(b,e){var d=Math.cos(e),f=Math.sin(e),h=1-d,i=b.x,g=b.y,j=b.z,k=h*i,o=h*g;this.set(k*i+d,k*g-f*j,k*j+f*g,0,k*g+f*j,o*g+d,o*j-f*i,0,k*j-f*g,o*j+f*i,h*j*j+d,0,0,0,0,1);return this},setPosition:function(b){this.n14=b.x;this.n24=b.y;this.n34=b.z;return this},getPosition:function(){if(!this.position)this.position=new THREE.Vector3;this.position.set(this.n14,this.n24,this.n34);return this.position},getColumnX:function(){if(!this.columnX)this.columnX=new THREE.Vector3;this.columnX.set(this.n11, +this.n21,this.n31);return this.columnX},getColumnY:function(){if(!this.columnY)this.columnY=new THREE.Vector3;this.columnY.set(this.n12,this.n22,this.n32);return this.columnY},getColumnZ:function(){if(!this.columnZ)this.columnZ=new THREE.Vector3;this.columnZ.set(this.n13,this.n23,this.n33);return this.columnZ},setRotationFromEuler:function(b,e){var d=b.x,f=b.y,h=b.z,i=Math.cos(d),d=Math.sin(d),g=Math.cos(f),f=Math.sin(f),j=Math.cos(h),h=Math.sin(h);switch(e){case "YXZ":var k=g*j,o=g*h,p=f*j,n=f*h; +this.n11=k+n*d;this.n12=p*d-o;this.n13=i*f;this.n21=i*h;this.n22=i*j;this.n23=-d;this.n31=o*d-p;this.n32=n+k*d;this.n33=i*g;break;case "ZXY":k=g*j;o=g*h;p=f*j;n=f*h;this.n11=k-n*d;this.n12=-i*h;this.n13=p+o*d;this.n21=o+p*d;this.n22=i*j;this.n23=n-k*d;this.n31=-i*f;this.n32=d;this.n33=i*g;break;case "ZYX":k=i*j;o=i*h;p=d*j;n=d*h;this.n11=g*j;this.n12=p*f-o;this.n13=k*f+n;this.n21=g*h;this.n22=n*f+k;this.n23=o*f-p;this.n31=-f;this.n32=d*g;this.n33=i*g;break;case "YZX":k=i*g;o=i*f;p=d*g;n=d*f;this.n11= +g*j;this.n12=n-k*h;this.n13=p*h+o;this.n21=h;this.n22=i*j;this.n23=-d*j;this.n31=-f*j;this.n32=o*h+p;this.n33=k-n*h;break;case "XZY":k=i*g;o=i*f;p=d*g;n=d*f;this.n11=g*j;this.n12=-h;this.n13=f*j;this.n21=k*h+n;this.n22=i*j;this.n23=o*h-p;this.n31=p*h-o;this.n32=d*j;this.n33=n*h+k;break;default:k=i*j,o=i*h,p=d*j,n=d*h,this.n11=g*j,this.n12=-g*h,this.n13=f,this.n21=o+p*f,this.n22=k-n*f,this.n23=-d*g,this.n31=n-k*f,this.n32=p+o*f,this.n33=i*g}return this},setRotationFromQuaternion:function(b){var e= b.x,d=b.y,f=b.z,h=b.w,i=e+e,g=d+d,j=f+f,b=e*i,k=e*g;e*=j;var o=d*g;d*=j;f*=j;i*=h;g*=h;h*=j;this.n11=1-(o+f);this.n12=k-h;this.n13=e+g;this.n21=k+h;this.n22=1-(b+f);this.n23=d-i;this.n31=e-g;this.n32=d+i;this.n33=1-(b+o);return this},scale:function(b){var e=b.x,d=b.y,b=b.z;this.n11*=e;this.n12*=d;this.n13*=b;this.n21*=e;this.n22*=d;this.n23*=b;this.n31*=e;this.n32*=d;this.n33*=b;this.n41*=e;this.n42*=d;this.n43*=b;return this},extractPosition:function(b){this.n14=b.n14;this.n24=b.n24;this.n34=b.n34}, extractRotation:function(b,e){var d=1/e.x,f=1/e.y,h=1/e.z;this.n11=b.n11*d;this.n21=b.n21*d;this.n31=b.n31*d;this.n12=b.n12*f;this.n22=b.n22*f;this.n32=b.n32*f;this.n13=b.n13*h;this.n23=b.n23*h;this.n33=b.n33*h}}; THREE.Matrix4.makeInvert=function(b,e){var d=b.n11,f=b.n12,h=b.n13,i=b.n14,g=b.n21,j=b.n22,k=b.n23,o=b.n24,p=b.n31,n=b.n32,q=b.n33,w=b.n34,y=b.n41,D=b.n42,z=b.n43,C=b.n44;e===void 0&&(e=new THREE.Matrix4);e.n11=k*w*D-o*q*D+o*n*z-j*w*z-k*n*C+j*q*C;e.n12=i*q*D-h*w*D-i*n*z+f*w*z+h*n*C-f*q*C;e.n13=h*o*D-i*k*D+i*j*z-f*o*z-h*j*C+f*k*C;e.n14=i*k*n-h*o*n-i*j*q+f*o*q+h*j*w-f*k*w;e.n21=o*q*y-k*w*y-o*p*z+g*w*z+k*p*C-g*q*C;e.n22=h*w*y-i*q*y+i*p*z-d*w*z-h*p*C+d*q*C;e.n23=i*k*y-h*o*y-i*g*z+d*o*z+h*g*C-d*k*C;e.n24= @@ -61,9 +61,9 @@ THREE.Geometry.prototype={computeCentroids:function(){var b,e,d;b=0;for(e=this.f d.centroid.addSelf(this.vertices[d.d].position),d.centroid.divideScalar(4))},computeFaceNormals:function(b){var e,d,f,h,i,g,j=new THREE.Vector3,k=new THREE.Vector3;f=0;for(h=this.faces.length;f0){this.boundingBox={x:[this.vertices[0].position.x,this.vertices[0].position.x],y:[this.vertices[0].position.y,this.vertices[0].position.y],z:[this.vertices[0].position.z,this.vertices[0].position.z]};for(var e=1,d=this.vertices.length;ethis.boundingBox.x[1])this.boundingBox.x[1]=b.position.x;if(b.position.ythis.boundingBox.y[1])this.boundingBox.y[1]=b.position.y;if(b.position.zthis.boundingBox.z[1])this.boundingBox.z[1]=b.position.z}}},computeBoundingSphere:function(){for(var b=0,e=0,d=this.vertices.length;e=0&&h>=0&&g>=0&&i>=0?!0:f<0&&h<0||g<0&&i<0?!1:(f<0?d=Math.max(d,f/(f-h)):h<0&&(c=Math.min(c,f/(f-h))),g<0?d=Math.max(d,g/(g-i)):i<0&&(c=Math.min(c,g/(g-i))),c=0&&h>=0&&g>=0&&i>=0?!0:f<0&&h<0||g<0&&i<0?!1:(f<0?d=Math.max(d,f/(f-h)):h<0&&(c=Math.min(c,f/(f-h))),g<0?d=Math.max(d,g/(g-i)):i<0&&(c=Math.min(c,g/(g-i))),cO&&g.positionScreen.z0&&F.z<1))t=M[ga]=M[ga]||new THREE.RenderableParticle,ga++,C=t,C.x=F.x/F.w,C.y=F.y/F.w,C.z=F.z,C.rotation=u.rotation.z,C.scale.x=u.scale.x*Math.abs(C.x-(F.x+h.projectionMatrix.n11)/ -(F.w+h.projectionMatrix.n14)),C.scale.y=u.scale.y*Math.abs(C.y-(F.y+h.projectionMatrix.n22)/(F.w+h.projectionMatrix.n24)),C.materials=u.materials,c.push(C);i&&c.sort(e);return c}}; +ua[E][la]){G=0;for(N=za.length;G0&&F.z<1))t=aa[ga]=aa[ga]||new THREE.RenderableParticle,ga++,C=t,C.x=F.x/F.w,C.y=F.y/F.w,C.z=F.z,C.rotation=u.rotation.z,C.scale.x=u.scale.x*Math.abs(C.x-(F.x+h.projectionMatrix.n11)/(F.w+ +h.projectionMatrix.n14)),C.scale.y=u.scale.y*Math.abs(C.y-(F.y+h.projectionMatrix.n22)/(F.w+h.projectionMatrix.n24)),C.materials=u.materials,c.push(C);i&&c.sort(e);return c}}; THREE.SoundRenderer=function(){this.volume=1;this.domElement=document.createElement("div");this.domElement.id="THREESound";this.cameraPosition=new THREE.Vector3;this.soundPosition=new THREE.Vector3;this.render=function(b,e,d){d&&b.update(void 0,!1,e);var d=b.sounds,f,h=d.length;for(f=0;f=0)c.bindBuffer(c.ARRAY_BUFFER,g.__webglVertexBuffer),c.vertexAttribPointer(b.position, 3,c.FLOAT,!1,0,0);else{e=h.program.attributes;i.morphTargetBase!==-1?(c.bindBuffer(c.ARRAY_BUFFER,g.__webglMorphTargetsBuffers[i.morphTargetBase]),c.vertexAttribPointer(e.position,3,c.FLOAT,!1,0,0)):e.position>=0&&(c.bindBuffer(c.ARRAY_BUFFER,g.__webglVertexBuffer),c.vertexAttribPointer(e.position,3,c.FLOAT,!1,0,0));if(i.morphTargetForcedOrder.length)for(var f=0,k=i.morphTargetForcedOrder,o=i.morphTargetInfluences;f=0;d--)b[d].object==c&&b.splice(d,1)}function O(b){function c(b){var f=[];d=0;for(e=b.length;d=0;d--)b[d].object==c&&b.splice(d,1)}function O(b){function c(b){var f=[];d=0;for(e=b.length;d65535&&(r[j].counter+=1,k=r[j].hash+"_"+r[j].counter,b.geometryGroups[k]==void 0&&(b.geometryGroups[k]={faces:[],materials:i,vertices:0,numMorphTargets:o})),b.geometryGroups[k].faces.push(f),b.geometryGroups[k].vertices+= h}function F(b,c,d){b.push({buffer:c,object:d,opaque:{list:[],count:0},transparent:{list:[],count:0}})}function v(b){if(b!=E){switch(b){case THREE.AdditiveBlending:c.blendEquation(c.FUNC_ADD);c.blendFunc(c.SRC_ALPHA,c.ONE);break;case THREE.SubtractiveBlending:c.blendEquation(c.FUNC_ADD);c.blendFunc(c.ZERO,c.ONE_MINUS_SRC_COLOR);break;case THREE.MultiplyBlending:c.blendEquation(c.FUNC_ADD);c.blendFunc(c.ZERO,c.SRC_COLOR);break;default:c.blendEquationSeparate(c.FUNC_ADD,c.FUNC_ADD),c.blendFuncSeparate(c.SRC_ALPHA, -c.ONE_MINUS_SRC_ALPHA,c.ONE,c.ONE_MINUS_SRC_ALPHA)}E=b}}function $(b,d,e){(e.width&e.width-1)==0&&(e.height&e.height-1)==0?(c.texParameteri(b,c.TEXTURE_WRAP_S,U(d.wrapS)),c.texParameteri(b,c.TEXTURE_WRAP_T,U(d.wrapT)),c.texParameteri(b,c.TEXTURE_MAG_FILTER,U(d.magFilter)),c.texParameteri(b,c.TEXTURE_MIN_FILTER,U(d.minFilter)),c.generateMipmap(b)):(c.texParameteri(b,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(b,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.texParameteri(b,c.TEXTURE_MAG_FILTER,na(d.magFilter)), -c.texParameteri(b,c.TEXTURE_MIN_FILTER,na(d.minFilter)))}function B(b,d){if(b.needsUpdate)b.__webglInit?(c.bindTexture(c.TEXTURE_2D,b.__webglTexture),c.texSubImage2D(c.TEXTURE_2D,0,0,0,c.RGBA,c.UNSIGNED_BYTE,b.image)):(b.__webglTexture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,b.__webglTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,c.RGBA,c.UNSIGNED_BYTE,b.image),b.__webglInit=!0),$(c.TEXTURE_2D,b,b.image),c.bindTexture(c.TEXTURE_2D,null),b.needsUpdate=!1;c.activeTexture(c.TEXTURE0+d);c.bindTexture(c.TEXTURE_2D, -b.__webglTexture)}function aa(b){if(b&&!b.__webglFramebuffer){if(b.depthBuffer===void 0)b.depthBuffer=!0;if(b.stencilBuffer===void 0)b.stencilBuffer=!0;b.__webglFramebuffer=c.createFramebuffer();b.__webglRenderbuffer=c.createRenderbuffer();b.__webglTexture=c.createTexture();c.bindTexture(c.TEXTURE_2D,b.__webglTexture);c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,U(b.wrapS));c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,U(b.wrapT));c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,U(b.magFilter)); +c.ONE_MINUS_SRC_ALPHA,c.ONE,c.ONE_MINUS_SRC_ALPHA)}E=b}}function M(b,d,e){(e.width&e.width-1)==0&&(e.height&e.height-1)==0?(c.texParameteri(b,c.TEXTURE_WRAP_S,U(d.wrapS)),c.texParameteri(b,c.TEXTURE_WRAP_T,U(d.wrapT)),c.texParameteri(b,c.TEXTURE_MAG_FILTER,U(d.magFilter)),c.texParameteri(b,c.TEXTURE_MIN_FILTER,U(d.minFilter)),c.generateMipmap(b)):(c.texParameteri(b,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(b,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.texParameteri(b,c.TEXTURE_MAG_FILTER,na(d.magFilter)), +c.texParameteri(b,c.TEXTURE_MIN_FILTER,na(d.minFilter)))}function B(b,d){if(b.needsUpdate)b.__webglInit?(c.bindTexture(c.TEXTURE_2D,b.__webglTexture),c.texSubImage2D(c.TEXTURE_2D,0,0,0,c.RGBA,c.UNSIGNED_BYTE,b.image)):(b.__webglTexture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,b.__webglTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,c.RGBA,c.UNSIGNED_BYTE,b.image),b.__webglInit=!0),M(c.TEXTURE_2D,b,b.image),c.bindTexture(c.TEXTURE_2D,null),b.needsUpdate=!1;c.activeTexture(c.TEXTURE0+d);c.bindTexture(c.TEXTURE_2D, +b.__webglTexture)}function $(b){if(b&&!b.__webglFramebuffer){if(b.depthBuffer===void 0)b.depthBuffer=!0;if(b.stencilBuffer===void 0)b.stencilBuffer=!0;b.__webglFramebuffer=c.createFramebuffer();b.__webglRenderbuffer=c.createRenderbuffer();b.__webglTexture=c.createTexture();c.bindTexture(c.TEXTURE_2D,b.__webglTexture);c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,U(b.wrapS));c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,U(b.wrapT));c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,U(b.magFilter)); c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,U(b.minFilter));c.texImage2D(c.TEXTURE_2D,0,U(b.format),b.width,b.height,0,U(b.format),U(b.type),null);c.bindRenderbuffer(c.RENDERBUFFER,b.__webglRenderbuffer);c.bindFramebuffer(c.FRAMEBUFFER,b.__webglFramebuffer);c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,b.__webglTexture,0);b.depthBuffer&&!b.stencilBuffer?(c.renderbufferStorage(c.RENDERBUFFER,c.DEPTH_COMPONENT16,b.width,b.height),c.framebufferRenderbuffer(c.FRAMEBUFFER, c.DEPTH_ATTACHMENT,c.RENDERBUFFER,b.__webglRenderbuffer)):b.depthBuffer&&b.stencilBuffer?(c.renderbufferStorage(c.RENDERBUFFER,c.DEPTH_STENCIL,b.width,b.height),c.framebufferRenderbuffer(c.FRAMEBUFFER,c.DEPTH_STENCIL_ATTACHMENT,c.RENDERBUFFER,b.__webglRenderbuffer)):c.renderbufferStorage(c.RENDERBUFFER,c.RGBA4,b.width,b.height);c.bindTexture(c.TEXTURE_2D,null);c.bindRenderbuffer(c.RENDERBUFFER,null);c.bindFramebuffer(c.FRAMEBUFFER,null)}var d,e;b?(d=b.__webglFramebuffer,e=b.width,b=b.height):(d=null, e=_viewportWidth,b=_viewportHeight);d!=ka&&(c.bindFramebuffer(c.FRAMEBUFFER,d),c.viewport(_viewportX,_viewportY,e,b),ka=d)}function K(b,d){var e;b=="fragment"?e=c.createShader(c.FRAGMENT_SHADER):b=="vertex"&&(e=c.createShader(c.VERTEX_SHADER));c.shaderSource(e,d);c.compileShader(e);if(!c.getShaderParameter(e,c.COMPILE_STATUS))return console.error(c.getShaderInfoLog(e)),console.error(d),null;return e}function na(b){switch(b){case THREE.NearestFilter:case THREE.NearestMipMapNearestFilter:case THREE.NearestMipMapLinearFilter:return c.NEAREST; @@ -285,7 +285,7 @@ q.length;j=0&&c.enableVertexAttribArray(n.tangent);b.skinning&&n.skinVertexA>=0&&n.skinVertexB>=0&&n.skinIndex>=0&&n.skinWeight>=0&&(c.enableVertexAttribArray(n.skinVertexA),c.enableVertexAttribArray(n.skinVertexB),c.enableVertexAttribArray(n.skinIndex),c.enableVertexAttribArray(n.skinWeight));if(b.attributes)for(g in b.attributes)n[g]!==void 0&&n[g]>=0&&c.enableVertexAttribArray(n[g]);if(b.morphTargets){b.numSupportedMorphTargets=0;n.morphTarget0>=0&&(c.enableVertexAttribArray(n.morphTarget0), b.numSupportedMorphTargets++);n.morphTarget1>=0&&(c.enableVertexAttribArray(n.morphTarget1),b.numSupportedMorphTargets++);n.morphTarget2>=0&&(c.enableVertexAttribArray(n.morphTarget2),b.numSupportedMorphTargets++);n.morphTarget3>=0&&(c.enableVertexAttribArray(n.morphTarget3),b.numSupportedMorphTargets++);n.morphTarget4>=0&&(c.enableVertexAttribArray(n.morphTarget4),b.numSupportedMorphTargets++);n.morphTarget5>=0&&(c.enableVertexAttribArray(n.morphTarget5),b.numSupportedMorphTargets++);n.morphTarget6>= 0&&(c.enableVertexAttribArray(n.morphTarget6),b.numSupportedMorphTargets++);n.morphTarget7>=0&&(c.enableVertexAttribArray(n.morphTarget7),b.numSupportedMorphTargets++);f.__webglMorphTargetInfluences=new Float32Array(this.maxMorphTargets);b=0;for(g=this.maxMorphTargets;b0||t.faceVertexUvs.length>0)i.__ p[z];if(!v.__webglInitialized||v.createUniqueBuffers)v.__webglInitialized=!0,u=1,v.type==="v2"?u=2:v.type==="v3"?u=3:v.type==="v4"?u=4:v.type==="c"&&(u=3),v.size=u,v.array=new Float32Array(k*u),v.buffer=c.createBuffer(),v.buffer.belongsToAttribute=a,p.needsUpdate=!0,v.__original=p;i.__webglCustomAttributes[a]=v}i.__inittedArrays=!0;g.__dirtyVertices=!0;g.__dirtyMorphTargets=!0;g.__dirtyElements=!0;g.__dirtyUvs=!0;g.__dirtyNormals=!0;g.__dirtyTangents=!0;g.__dirtyColors=!0}d instanceof THREE.ShadowVolume? F(e.__webglShadowVolumes,h,d):F(e.__webglObjects,h,d)}else if(d instanceof THREE.LensFlare)F(e.__webglLensFlares,void 0,d);else if(d instanceof THREE.Ribbon){g=d.geometry;if(!g.__webglVertexBuffer)f=g,f.__webglVertexBuffer=c.createBuffer(),f.__webglColorBuffer=c.createBuffer(),f=g,h=f.vertices.length,f.__vertexArray=new Float32Array(h*3),f.__colorArray=new Float32Array(h*3),f.__webglVertexCount=h,g.__dirtyVertices=!0,g.__dirtyColors=!0;F(e.__webglObjects,g,d)}else if(d instanceof THREE.Line){g=d.geometry; if(!g.__webglVertexBuffer)f=g,f.__webglVertexBuffer=c.createBuffer(),f.__webglColorBuffer=c.createBuffer(),f=g,h=f.vertices.length,f.__vertexArray=new Float32Array(h*3),f.__colorArray=new Float32Array(h*3),f.__webglLineCount=h,g.__dirtyVertices=!0,g.__dirtyColors=!0;F(e.__webglObjects,g,d)}else if(d instanceof THREE.ParticleSystem){g=d.geometry;if(!g.__webglVertexBuffer)f=g,f.__webglVertexBuffer=c.createBuffer(),f.__webglColorBuffer=c.createBuffer(),f=g,h=f.vertices.length,f.__vertexArray=new Float32Array(h* -3),f.__colorArray=new Float32Array(h*3),f.__sortArray=[],f.__webglParticleCount=h,g.__dirtyVertices=!0,g.__dirtyColors=!0;F(e.__webglObjects,g,d)}else THREE.MarchingCubes!==void 0&&d instanceof THREE.MarchingCubes?e.__webglObjectsImmediate.push({object:d,opaque:{list:[],count:0},transparent:{list:[],count:0}}):d instanceof THREE.Sprite&&e.__webglSprites.push(d);b.__objectsAdded.splice(0,1)}for(;b.__objectsRemoved.length;)d=b.__objectsRemoved[0],e=b,d instanceof THREE.ShadowVolume?M(e.__webglShadowVolumes, -d):d instanceof THREE.Mesh||d instanceof THREE.ParticleSystem||d instanceof THREE.Ribbon||d instanceof THREE.Line?M(e.__webglObjects,d):d instanceof THREE.Sprite?M(e.__webglSprites,d):d instanceof THREE.LensFlare?M(e.__webglLensFlares,d):d instanceof THREE.MarchingCubes&&M(e.__webglObjectsImmediate,d),b.__objectsRemoved.splice(0,1);d=0;for(e=b.__webglObjects.length;d=0;g--)d[g]==e&&d.splice(g,1)}else e instanceof THREE.LensFlare?aa(d.__webglLensFlares,e):e instanceof THREE.MarchingCubes&&aa(d.__webglObjectsImmediate,e);b.__objectsRemoved.splice(0,1)}d=0;for(e=b.__webglObjects.length;d