mirror of
https://github.com/xibyte/jsketcher
synced 2026-01-29 19:44:23 +01:00
update three.js lin to r72
This commit is contained in:
parent
f0236c6444
commit
eef3c9ffe4
221 changed files with 17320 additions and 53206 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -1,12 +1,14 @@
|
|||
/**
|
||||
* @author Eberhard Graether / http://egraether.com/
|
||||
* @author Mark Lundin / http://mark-lundin.com
|
||||
* @author Simone Manini / http://daron1337.github.io
|
||||
* @author Luca Antiga / http://lantiga.github.io
|
||||
*/
|
||||
|
||||
THREE.TrackballControls = function ( object, domElement ) {
|
||||
|
||||
var _this = this;
|
||||
var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
|
||||
var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
|
||||
|
||||
this.object = object;
|
||||
this.domElement = ( domElement !== undefined ) ? domElement : document;
|
||||
|
|
@ -24,7 +26,6 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
this.noRotate = false;
|
||||
this.noZoom = false;
|
||||
this.noPan = false;
|
||||
this.noRoll = false;
|
||||
|
||||
this.staticMoving = false;
|
||||
this.dynamicDampingFactor = 0.2;
|
||||
|
|
@ -47,8 +48,11 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
|
||||
_eye = new THREE.Vector3(),
|
||||
|
||||
_rotateStart = new THREE.Vector3(),
|
||||
_rotateEnd = new THREE.Vector3(),
|
||||
_movePrev = new THREE.Vector2(),
|
||||
_moveCurr = new THREE.Vector2(),
|
||||
|
||||
_lastAxis = new THREE.Vector3(),
|
||||
_lastAngle = 0,
|
||||
|
||||
_zoomStart = new THREE.Vector2(),
|
||||
_zoomEnd = new THREE.Vector2(),
|
||||
|
|
@ -68,8 +72,8 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
// events
|
||||
|
||||
var changeEvent = { type: 'change' };
|
||||
var startEvent = { type: 'start'};
|
||||
var endEvent = { type: 'end'};
|
||||
var startEvent = { type: 'start' };
|
||||
var endEvent = { type: 'end' };
|
||||
|
||||
|
||||
// methods
|
||||
|
|
@ -111,7 +115,7 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
|
||||
var vector = new THREE.Vector2();
|
||||
|
||||
return function ( pageX, pageY ) {
|
||||
return function getMouseOnScreen( pageX, pageY ) {
|
||||
|
||||
vector.set(
|
||||
( pageX - _this.screen.left ) / _this.screen.width,
|
||||
|
|
@ -124,106 +128,92 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
|
||||
}() );
|
||||
|
||||
var getMouseProjectionOnBall = ( function () {
|
||||
var getMouseOnCircle = ( function () {
|
||||
|
||||
var vector = new THREE.Vector3();
|
||||
var objectUp = new THREE.Vector3();
|
||||
var mouseOnBall = new THREE.Vector3();
|
||||
var vector = new THREE.Vector2();
|
||||
|
||||
return function ( pageX, pageY ) {
|
||||
return function getMouseOnCircle( pageX, pageY ) {
|
||||
|
||||
mouseOnBall.set(
|
||||
( pageX - _this.screen.width * 0.5 - _this.screen.left ) / (_this.screen.width*.5),
|
||||
( _this.screen.height * 0.5 + _this.screen.top - pageY ) / (_this.screen.height*.5),
|
||||
0.0
|
||||
vector.set(
|
||||
( ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ) ),
|
||||
( ( _this.screen.height + 2 * ( _this.screen.top - pageY ) ) / _this.screen.width ) // screen.width intentional
|
||||
);
|
||||
|
||||
var length = mouseOnBall.length();
|
||||
|
||||
if ( _this.noRoll ) {
|
||||
|
||||
if ( length < Math.SQRT1_2 ) {
|
||||
|
||||
mouseOnBall.z = Math.sqrt( 1.0 - length*length );
|
||||
|
||||
} else {
|
||||
|
||||
mouseOnBall.z = .5 / length;
|
||||
|
||||
}
|
||||
|
||||
} else if ( length > 1.0 ) {
|
||||
|
||||
mouseOnBall.normalize();
|
||||
|
||||
} else {
|
||||
|
||||
mouseOnBall.z = Math.sqrt( 1.0 - length * length );
|
||||
|
||||
}
|
||||
|
||||
_eye.copy( _this.object.position ).sub( _this.target );
|
||||
|
||||
vector.copy( _this.object.up ).setLength( mouseOnBall.y )
|
||||
vector.add( objectUp.copy( _this.object.up ).cross( _eye ).setLength( mouseOnBall.x ) );
|
||||
vector.add( _eye.setLength( mouseOnBall.z ) );
|
||||
|
||||
return vector;
|
||||
|
||||
};
|
||||
|
||||
}() );
|
||||
|
||||
this.rotateCamera = (function(){
|
||||
this.rotateCamera = ( function() {
|
||||
|
||||
var axis = new THREE.Vector3(),
|
||||
quaternion = new THREE.Quaternion();
|
||||
quaternion = new THREE.Quaternion(),
|
||||
eyeDirection = new THREE.Vector3(),
|
||||
objectUpDirection = new THREE.Vector3(),
|
||||
objectSidewaysDirection = new THREE.Vector3(),
|
||||
moveDirection = new THREE.Vector3(),
|
||||
angle;
|
||||
|
||||
return function rotateCamera() {
|
||||
|
||||
return function () {
|
||||
|
||||
var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
|
||||
moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );
|
||||
angle = moveDirection.length();
|
||||
|
||||
if ( angle ) {
|
||||
|
||||
axis.crossVectors( _rotateStart, _rotateEnd ).normalize();
|
||||
_eye.copy( _this.object.position ).sub( _this.target );
|
||||
|
||||
eyeDirection.copy( _eye ).normalize();
|
||||
objectUpDirection.copy( _this.object.up ).normalize();
|
||||
objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize();
|
||||
|
||||
objectUpDirection.setLength( _moveCurr.y - _movePrev.y );
|
||||
objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x );
|
||||
|
||||
moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) );
|
||||
|
||||
axis.crossVectors( moveDirection, _eye ).normalize();
|
||||
|
||||
angle *= _this.rotateSpeed;
|
||||
|
||||
quaternion.setFromAxisAngle( axis, -angle );
|
||||
quaternion.setFromAxisAngle( axis, angle );
|
||||
|
||||
_eye.applyQuaternion( quaternion );
|
||||
_this.object.up.applyQuaternion( quaternion );
|
||||
|
||||
_rotateEnd.applyQuaternion( quaternion );
|
||||
_lastAxis.copy( axis );
|
||||
_lastAngle = angle;
|
||||
|
||||
if ( _this.staticMoving ) {
|
||||
} else if ( ! _this.staticMoving && _lastAngle ) {
|
||||
|
||||
_rotateStart.copy( _rotateEnd );
|
||||
|
||||
} else {
|
||||
|
||||
quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
|
||||
_rotateStart.applyQuaternion( quaternion );
|
||||
|
||||
}
|
||||
_lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor );
|
||||
_eye.copy( _this.object.position ).sub( _this.target );
|
||||
quaternion.setFromAxisAngle( _lastAxis, _lastAngle );
|
||||
_eye.applyQuaternion( quaternion );
|
||||
_this.object.up.applyQuaternion( quaternion );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}());
|
||||
_movePrev.copy( _moveCurr );
|
||||
|
||||
};
|
||||
|
||||
}() );
|
||||
|
||||
|
||||
this.zoomCamera = function () {
|
||||
|
||||
var factor;
|
||||
|
||||
if ( _state === STATE.TOUCH_ZOOM_PAN ) {
|
||||
|
||||
var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
|
||||
factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
|
||||
_touchZoomDistanceStart = _touchZoomDistanceEnd;
|
||||
_eye.multiplyScalar( factor );
|
||||
|
||||
} else {
|
||||
|
||||
var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
|
||||
factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
|
||||
|
||||
if ( factor !== 1.0 && factor > 0.0 ) {
|
||||
|
||||
|
|
@ -245,13 +235,13 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
|
||||
};
|
||||
|
||||
this.panCamera = (function(){
|
||||
this.panCamera = ( function() {
|
||||
|
||||
var mouseChange = new THREE.Vector2(),
|
||||
objectUp = new THREE.Vector3(),
|
||||
pan = new THREE.Vector3();
|
||||
|
||||
return function () {
|
||||
return function panCamera() {
|
||||
|
||||
mouseChange.copy( _panEnd ).sub( _panStart );
|
||||
|
||||
|
|
@ -276,23 +266,26 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}());
|
||||
};
|
||||
|
||||
}() );
|
||||
|
||||
this.checkDistances = function () {
|
||||
|
||||
if ( !_this.noZoom || !_this.noPan ) {
|
||||
if ( ! _this.noZoom || ! _this.noPan ) {
|
||||
|
||||
if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) {
|
||||
|
||||
_this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) );
|
||||
_zoomStart.copy( _zoomEnd );
|
||||
|
||||
}
|
||||
|
||||
if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {
|
||||
|
||||
_this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) );
|
||||
_zoomStart.copy( _zoomEnd );
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -304,19 +297,19 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
|
||||
_eye.subVectors( _this.object.position, _this.target );
|
||||
|
||||
if ( !_this.noRotate ) {
|
||||
if ( ! _this.noRotate ) {
|
||||
|
||||
_this.rotateCamera();
|
||||
|
||||
}
|
||||
|
||||
if ( !_this.noZoom ) {
|
||||
if ( ! _this.noZoom ) {
|
||||
|
||||
_this.zoomCamera();
|
||||
|
||||
}
|
||||
|
||||
if ( !_this.noPan ) {
|
||||
if ( ! _this.noPan ) {
|
||||
|
||||
_this.panCamera();
|
||||
|
||||
|
|
@ -371,15 +364,15 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
|
||||
return;
|
||||
|
||||
} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) {
|
||||
} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && ! _this.noRotate ) {
|
||||
|
||||
_state = STATE.ROTATE;
|
||||
|
||||
} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) {
|
||||
} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && ! _this.noZoom ) {
|
||||
|
||||
_state = STATE.ZOOM;
|
||||
|
||||
} else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) {
|
||||
} else if ( event.keyCode === _this.keys[ STATE.PAN ] && ! _this.noPan ) {
|
||||
|
||||
_state = STATE.PAN;
|
||||
|
||||
|
|
@ -410,20 +403,20 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
|
||||
}
|
||||
|
||||
if ( _state === STATE.ROTATE && !_this.noRotate ) {
|
||||
if ( _state === STATE.ROTATE && ! _this.noRotate ) {
|
||||
|
||||
_rotateStart.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
|
||||
_rotateEnd.copy( _rotateStart );
|
||||
_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
|
||||
_movePrev.copy( _moveCurr );
|
||||
|
||||
} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
|
||||
} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
|
||||
|
||||
_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
|
||||
_zoomEnd.copy(_zoomStart);
|
||||
_zoomEnd.copy( _zoomStart );
|
||||
|
||||
} else if ( _state === STATE.PAN && !_this.noPan ) {
|
||||
} else if ( _state === STATE.PAN && ! _this.noPan ) {
|
||||
|
||||
_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
|
||||
_panEnd.copy(_panStart)
|
||||
_panEnd.copy( _panStart );
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -441,15 +434,16 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
if ( _state === STATE.ROTATE && !_this.noRotate ) {
|
||||
if ( _state === STATE.ROTATE && ! _this.noRotate ) {
|
||||
|
||||
_rotateEnd.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
|
||||
_movePrev.copy( _moveCurr );
|
||||
_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
|
||||
|
||||
} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
|
||||
} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
|
||||
|
||||
_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
|
||||
|
||||
} else if ( _state === STATE.PAN && !_this.noPan ) {
|
||||
} else if ( _state === STATE.PAN && ! _this.noPan ) {
|
||||
|
||||
_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
|
||||
|
||||
|
|
@ -481,11 +475,15 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
|
||||
var delta = 0;
|
||||
|
||||
if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
|
||||
if ( event.wheelDelta ) {
|
||||
|
||||
// WebKit / Opera / Explorer 9
|
||||
|
||||
delta = event.wheelDelta / 40;
|
||||
|
||||
} else if ( event.detail ) { // Firefox
|
||||
} else if ( event.detail ) {
|
||||
|
||||
// Firefox
|
||||
|
||||
delta = - event.detail / 3;
|
||||
|
||||
|
|
@ -505,8 +503,8 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
|
||||
case 1:
|
||||
_state = STATE.TOUCH_ROTATE;
|
||||
_rotateStart.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
|
||||
_rotateEnd.copy( _rotateStart );
|
||||
_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
|
||||
_movePrev.copy( _moveCurr );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
|
@ -540,7 +538,8 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
switch ( event.touches.length ) {
|
||||
|
||||
case 1:
|
||||
_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
|
||||
_movePrev.copy( _moveCurr );
|
||||
_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
|
@ -567,8 +566,8 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
switch ( event.touches.length ) {
|
||||
|
||||
case 1:
|
||||
_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
|
||||
_rotateStart.copy( _rotateEnd );
|
||||
_movePrev.copy( _moveCurr );
|
||||
_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
|
@ -587,10 +586,33 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
|
||||
}
|
||||
|
||||
this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
|
||||
function contextmenu( event ) {
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
}
|
||||
|
||||
this.dispose = function() {
|
||||
|
||||
this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
|
||||
this.domElement.removeEventListener( 'mousedown', mousedown, false );
|
||||
this.domElement.removeEventListener( 'mousewheel', mousewheel, false );
|
||||
this.domElement.removeEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
|
||||
|
||||
this.domElement.removeEventListener( 'touchstart', touchstart, false );
|
||||
this.domElement.removeEventListener( 'touchend', touchend, false );
|
||||
this.domElement.removeEventListener( 'touchmove', touchmove, false );
|
||||
|
||||
document.removeEventListener( 'mousemove', mousemove, false );
|
||||
document.removeEventListener( 'mouseup', mouseup, false );
|
||||
|
||||
window.removeEventListener( 'keydown', keydown, false );
|
||||
window.removeEventListener( 'keyup', keyup, false );
|
||||
|
||||
}
|
||||
|
||||
this.domElement.addEventListener( 'contextmenu', contextmenu, false );
|
||||
this.domElement.addEventListener( 'mousedown', mousedown, false );
|
||||
|
||||
this.domElement.addEventListener( 'mousewheel', mousewheel, false );
|
||||
this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
|
||||
|
||||
|
|
@ -609,3 +631,4 @@ THREE.TrackballControls = function ( object, domElement ) {
|
|||
};
|
||||
|
||||
THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );
|
||||
THREE.TrackballControls.prototype.constructor = THREE.TrackballControls;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,160 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
var THREE = { REVISION: '68' };
|
||||
|
||||
// browserify support
|
||||
if ( typeof module === 'object' ) {
|
||||
|
||||
module.exports = THREE;
|
||||
|
||||
}
|
||||
|
||||
// GL STATE CONSTANTS
|
||||
|
||||
THREE.CullFaceNone = 0;
|
||||
THREE.CullFaceBack = 1;
|
||||
THREE.CullFaceFront = 2;
|
||||
THREE.CullFaceFrontBack = 3;
|
||||
|
||||
THREE.FrontFaceDirectionCW = 0;
|
||||
THREE.FrontFaceDirectionCCW = 1;
|
||||
|
||||
// SHADOWING TYPES
|
||||
|
||||
THREE.BasicShadowMap = 0;
|
||||
THREE.PCFShadowMap = 1;
|
||||
THREE.PCFSoftShadowMap = 2;
|
||||
|
||||
// MATERIAL CONSTANTS
|
||||
|
||||
// side
|
||||
|
||||
THREE.FrontSide = 0;
|
||||
THREE.BackSide = 1;
|
||||
THREE.DoubleSide = 2;
|
||||
|
||||
// shading
|
||||
|
||||
THREE.NoShading = 0;
|
||||
THREE.FlatShading = 1;
|
||||
THREE.SmoothShading = 2;
|
||||
|
||||
// colors
|
||||
|
||||
THREE.NoColors = 0;
|
||||
THREE.FaceColors = 1;
|
||||
THREE.VertexColors = 2;
|
||||
|
||||
// blending modes
|
||||
|
||||
THREE.NoBlending = 0;
|
||||
THREE.NormalBlending = 1;
|
||||
THREE.AdditiveBlending = 2;
|
||||
THREE.SubtractiveBlending = 3;
|
||||
THREE.MultiplyBlending = 4;
|
||||
THREE.CustomBlending = 5;
|
||||
|
||||
// custom blending equations
|
||||
// (numbers start from 100 not to clash with other
|
||||
// mappings to OpenGL constants defined in Texture.js)
|
||||
|
||||
THREE.AddEquation = 100;
|
||||
THREE.SubtractEquation = 101;
|
||||
THREE.ReverseSubtractEquation = 102;
|
||||
|
||||
// custom blending destination factors
|
||||
|
||||
THREE.ZeroFactor = 200;
|
||||
THREE.OneFactor = 201;
|
||||
THREE.SrcColorFactor = 202;
|
||||
THREE.OneMinusSrcColorFactor = 203;
|
||||
THREE.SrcAlphaFactor = 204;
|
||||
THREE.OneMinusSrcAlphaFactor = 205;
|
||||
THREE.DstAlphaFactor = 206;
|
||||
THREE.OneMinusDstAlphaFactor = 207;
|
||||
|
||||
// custom blending source factors
|
||||
|
||||
//THREE.ZeroFactor = 200;
|
||||
//THREE.OneFactor = 201;
|
||||
//THREE.SrcAlphaFactor = 204;
|
||||
//THREE.OneMinusSrcAlphaFactor = 205;
|
||||
//THREE.DstAlphaFactor = 206;
|
||||
//THREE.OneMinusDstAlphaFactor = 207;
|
||||
THREE.DstColorFactor = 208;
|
||||
THREE.OneMinusDstColorFactor = 209;
|
||||
THREE.SrcAlphaSaturateFactor = 210;
|
||||
|
||||
|
||||
// TEXTURE CONSTANTS
|
||||
|
||||
THREE.MultiplyOperation = 0;
|
||||
THREE.MixOperation = 1;
|
||||
THREE.AddOperation = 2;
|
||||
|
||||
// Mapping modes
|
||||
|
||||
THREE.UVMapping = function () {};
|
||||
|
||||
THREE.CubeReflectionMapping = function () {};
|
||||
THREE.CubeRefractionMapping = function () {};
|
||||
|
||||
THREE.SphericalReflectionMapping = function () {};
|
||||
THREE.SphericalRefractionMapping = function () {};
|
||||
|
||||
// Wrapping modes
|
||||
|
||||
THREE.RepeatWrapping = 1000;
|
||||
THREE.ClampToEdgeWrapping = 1001;
|
||||
THREE.MirroredRepeatWrapping = 1002;
|
||||
|
||||
// Filters
|
||||
|
||||
THREE.NearestFilter = 1003;
|
||||
THREE.NearestMipMapNearestFilter = 1004;
|
||||
THREE.NearestMipMapLinearFilter = 1005;
|
||||
THREE.LinearFilter = 1006;
|
||||
THREE.LinearMipMapNearestFilter = 1007;
|
||||
THREE.LinearMipMapLinearFilter = 1008;
|
||||
|
||||
// Data types
|
||||
|
||||
THREE.UnsignedByteType = 1009;
|
||||
THREE.ByteType = 1010;
|
||||
THREE.ShortType = 1011;
|
||||
THREE.UnsignedShortType = 1012;
|
||||
THREE.IntType = 1013;
|
||||
THREE.UnsignedIntType = 1014;
|
||||
THREE.FloatType = 1015;
|
||||
|
||||
// Pixel types
|
||||
|
||||
//THREE.UnsignedByteType = 1009;
|
||||
THREE.UnsignedShort4444Type = 1016;
|
||||
THREE.UnsignedShort5551Type = 1017;
|
||||
THREE.UnsignedShort565Type = 1018;
|
||||
|
||||
// Pixel formats
|
||||
|
||||
THREE.AlphaFormat = 1019;
|
||||
THREE.RGBFormat = 1020;
|
||||
THREE.RGBAFormat = 1021;
|
||||
THREE.LuminanceFormat = 1022;
|
||||
THREE.LuminanceAlphaFormat = 1023;
|
||||
|
||||
// Compressed texture formats
|
||||
|
||||
THREE.RGB_S3TC_DXT1_Format = 2001;
|
||||
THREE.RGBA_S3TC_DXT1_Format = 2002;
|
||||
THREE.RGBA_S3TC_DXT3_Format = 2003;
|
||||
THREE.RGBA_S3TC_DXT5_Format = 2004;
|
||||
|
||||
/*
|
||||
// Potential future PVRTC compressed texture formats
|
||||
THREE.RGB_PVRTC_4BPPV1_Format = 2100;
|
||||
THREE.RGB_PVRTC_2BPPV1_Format = 2101;
|
||||
THREE.RGBA_PVRTC_4BPPV1_Format = 2102;
|
||||
THREE.RGBA_PVRTC_2BPPV1_Format = 2103;
|
||||
*/
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author mikael emtinger / http://gomo.se/
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
*/
|
||||
|
||||
THREE.Camera = function () {
|
||||
|
||||
THREE.Object3D.call( this );
|
||||
|
||||
this.matrixWorldInverse = new THREE.Matrix4();
|
||||
this.projectionMatrix = new THREE.Matrix4();
|
||||
|
||||
};
|
||||
|
||||
THREE.Camera.prototype = Object.create( THREE.Object3D.prototype );
|
||||
|
||||
THREE.Camera.prototype.lookAt = function () {
|
||||
|
||||
// This routine does not support cameras with rotated and/or translated parent(s)
|
||||
|
||||
var m1 = new THREE.Matrix4();
|
||||
|
||||
return function ( vector ) {
|
||||
|
||||
m1.lookAt( this.position, vector, this.up );
|
||||
|
||||
this.quaternion.setFromRotationMatrix( m1 );
|
||||
|
||||
};
|
||||
|
||||
}();
|
||||
|
||||
THREE.Camera.prototype.clone = function ( camera ) {
|
||||
|
||||
if ( camera === undefined ) camera = new THREE.Camera();
|
||||
|
||||
THREE.Object3D.prototype.clone.call( this, camera );
|
||||
|
||||
camera.matrixWorldInverse.copy( this.matrixWorldInverse );
|
||||
camera.projectionMatrix.copy( this.projectionMatrix );
|
||||
|
||||
return camera;
|
||||
};
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/**
|
||||
* Camera for rendering cube maps
|
||||
* - renders scene into axis-aligned cube
|
||||
*
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.CubeCamera = function ( near, far, cubeResolution ) {
|
||||
|
||||
THREE.Object3D.call( this );
|
||||
|
||||
var fov = 90, aspect = 1;
|
||||
|
||||
var cameraPX = new THREE.PerspectiveCamera( fov, aspect, near, far );
|
||||
cameraPX.up.set( 0, - 1, 0 );
|
||||
cameraPX.lookAt( new THREE.Vector3( 1, 0, 0 ) );
|
||||
this.add( cameraPX );
|
||||
|
||||
var cameraNX = new THREE.PerspectiveCamera( fov, aspect, near, far );
|
||||
cameraNX.up.set( 0, - 1, 0 );
|
||||
cameraNX.lookAt( new THREE.Vector3( - 1, 0, 0 ) );
|
||||
this.add( cameraNX );
|
||||
|
||||
var cameraPY = new THREE.PerspectiveCamera( fov, aspect, near, far );
|
||||
cameraPY.up.set( 0, 0, 1 );
|
||||
cameraPY.lookAt( new THREE.Vector3( 0, 1, 0 ) );
|
||||
this.add( cameraPY );
|
||||
|
||||
var cameraNY = new THREE.PerspectiveCamera( fov, aspect, near, far );
|
||||
cameraNY.up.set( 0, 0, - 1 );
|
||||
cameraNY.lookAt( new THREE.Vector3( 0, - 1, 0 ) );
|
||||
this.add( cameraNY );
|
||||
|
||||
var cameraPZ = new THREE.PerspectiveCamera( fov, aspect, near, far );
|
||||
cameraPZ.up.set( 0, - 1, 0 );
|
||||
cameraPZ.lookAt( new THREE.Vector3( 0, 0, 1 ) );
|
||||
this.add( cameraPZ );
|
||||
|
||||
var cameraNZ = new THREE.PerspectiveCamera( fov, aspect, near, far );
|
||||
cameraNZ.up.set( 0, - 1, 0 );
|
||||
cameraNZ.lookAt( new THREE.Vector3( 0, 0, - 1 ) );
|
||||
this.add( cameraNZ );
|
||||
|
||||
this.renderTarget = new THREE.WebGLRenderTargetCube( cubeResolution, cubeResolution, { format: THREE.RGBFormat, magFilter: THREE.LinearFilter, minFilter: THREE.LinearFilter } );
|
||||
|
||||
this.updateCubeMap = function ( renderer, scene ) {
|
||||
|
||||
var renderTarget = this.renderTarget;
|
||||
var generateMipmaps = renderTarget.generateMipmaps;
|
||||
|
||||
renderTarget.generateMipmaps = false;
|
||||
|
||||
renderTarget.activeCubeFace = 0;
|
||||
renderer.render( scene, cameraPX, renderTarget );
|
||||
|
||||
renderTarget.activeCubeFace = 1;
|
||||
renderer.render( scene, cameraNX, renderTarget );
|
||||
|
||||
renderTarget.activeCubeFace = 2;
|
||||
renderer.render( scene, cameraPY, renderTarget );
|
||||
|
||||
renderTarget.activeCubeFace = 3;
|
||||
renderer.render( scene, cameraNY, renderTarget );
|
||||
|
||||
renderTarget.activeCubeFace = 4;
|
||||
renderer.render( scene, cameraPZ, renderTarget );
|
||||
|
||||
renderTarget.generateMipmaps = generateMipmaps;
|
||||
|
||||
renderTarget.activeCubeFace = 5;
|
||||
renderer.render( scene, cameraNZ, renderTarget );
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
THREE.CubeCamera.prototype = Object.create( THREE.Object3D.prototype );
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.OrthographicCamera = function ( left, right, top, bottom, near, far ) {
|
||||
|
||||
THREE.Camera.call( this );
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.top = top;
|
||||
this.bottom = bottom;
|
||||
|
||||
this.near = ( near !== undefined ) ? near : 0.1;
|
||||
this.far = ( far !== undefined ) ? far : 2000;
|
||||
|
||||
this.updateProjectionMatrix();
|
||||
|
||||
};
|
||||
|
||||
THREE.OrthographicCamera.prototype = Object.create( THREE.Camera.prototype );
|
||||
|
||||
THREE.OrthographicCamera.prototype.updateProjectionMatrix = function () {
|
||||
|
||||
this.projectionMatrix.makeOrthographic( this.left, this.right, this.top, this.bottom, this.near, this.far );
|
||||
|
||||
};
|
||||
|
||||
THREE.OrthographicCamera.prototype.clone = function () {
|
||||
|
||||
var camera = new THREE.OrthographicCamera();
|
||||
|
||||
THREE.Camera.prototype.clone.call( this, camera );
|
||||
|
||||
camera.left = this.left;
|
||||
camera.right = this.right;
|
||||
camera.top = this.top;
|
||||
camera.bottom = this.bottom;
|
||||
|
||||
camera.near = this.near;
|
||||
camera.far = this.far;
|
||||
|
||||
return camera;
|
||||
};
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author greggman / http://games.greggman.com/
|
||||
* @author zz85 / http://www.lab4games.net/zz85/blog
|
||||
*/
|
||||
|
||||
THREE.PerspectiveCamera = function ( fov, aspect, near, far ) {
|
||||
|
||||
THREE.Camera.call( this );
|
||||
|
||||
this.fov = fov !== undefined ? fov : 50;
|
||||
this.aspect = aspect !== undefined ? aspect : 1;
|
||||
this.near = near !== undefined ? near : 0.1;
|
||||
this.far = far !== undefined ? far : 2000;
|
||||
|
||||
this.updateProjectionMatrix();
|
||||
|
||||
};
|
||||
|
||||
THREE.PerspectiveCamera.prototype = Object.create( THREE.Camera.prototype );
|
||||
|
||||
|
||||
/**
|
||||
* Uses Focal Length (in mm) to estimate and set FOV
|
||||
* 35mm (fullframe) camera is used if frame size is not specified;
|
||||
* Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html
|
||||
*/
|
||||
|
||||
THREE.PerspectiveCamera.prototype.setLens = function ( focalLength, frameHeight ) {
|
||||
|
||||
if ( frameHeight === undefined ) frameHeight = 24;
|
||||
|
||||
this.fov = 2 * THREE.Math.radToDeg( Math.atan( frameHeight / ( focalLength * 2 ) ) );
|
||||
this.updateProjectionMatrix();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 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.PerspectiveCamera.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.PerspectiveCamera.prototype.updateProjectionMatrix = function () {
|
||||
|
||||
if ( this.fullWidth ) {
|
||||
|
||||
var aspect = this.fullWidth / this.fullHeight;
|
||||
var top = Math.tan( THREE.Math.degToRad( this.fov * 0.5 ) ) * 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.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.makePerspective( this.fov, this.aspect, this.near, this.far );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.PerspectiveCamera.prototype.clone = function () {
|
||||
|
||||
var camera = new THREE.PerspectiveCamera();
|
||||
|
||||
THREE.Camera.prototype.clone.call( this, camera );
|
||||
|
||||
camera.fov = this.fov;
|
||||
camera.aspect = this.aspect;
|
||||
camera.near = this.near;
|
||||
camera.far = this.far;
|
||||
|
||||
return camera;
|
||||
};
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.BufferAttribute = function ( array, itemSize ) {
|
||||
|
||||
this.array = array;
|
||||
this.itemSize = itemSize;
|
||||
|
||||
};
|
||||
|
||||
THREE.BufferAttribute.prototype = {
|
||||
|
||||
constructor: THREE.BufferAttribute,
|
||||
|
||||
get length () {
|
||||
|
||||
return this.array.length;
|
||||
|
||||
},
|
||||
|
||||
set: function ( value ) {
|
||||
|
||||
this.array.set( value );
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setX: function ( index, x ) {
|
||||
|
||||
this.array[ index * this.itemSize ] = x;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setY: function ( index, y ) {
|
||||
|
||||
this.array[ index * this.itemSize + 1 ] = y;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setZ: function ( index, z ) {
|
||||
|
||||
this.array[ index * this.itemSize + 2 ] = z;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setXY: function ( index, x, y ) {
|
||||
|
||||
index *= this.itemSize;
|
||||
|
||||
this.array[ index ] = x;
|
||||
this.array[ index + 1 ] = y;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setXYZ: function ( index, x, y, z ) {
|
||||
|
||||
index *= this.itemSize;
|
||||
|
||||
this.array[ index ] = x;
|
||||
this.array[ index + 1 ] = y;
|
||||
this.array[ index + 2 ] = z;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setXYZW: function ( index, x, y, z, w ) {
|
||||
|
||||
index *= this.itemSize;
|
||||
|
||||
this.array[ index ] = x;
|
||||
this.array[ index + 1 ] = y;
|
||||
this.array[ index + 2 ] = z;
|
||||
this.array[ index + 3 ] = w;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
THREE.Int8Attribute = function ( data, itemSize ) {
|
||||
|
||||
console.warn( 'THREE.Int8Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' );
|
||||
return new THREE.BufferAttribute( data, itemSize );
|
||||
|
||||
};
|
||||
|
||||
THREE.Uint8Attribute = function ( data, itemSize ) {
|
||||
|
||||
console.warn( 'THREE.Uint8Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' );
|
||||
return new THREE.BufferAttribute( data, itemSize );
|
||||
|
||||
};
|
||||
|
||||
THREE.Uint8ClampedAttribute = function ( data, itemSize ) {
|
||||
|
||||
console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' );
|
||||
return new THREE.BufferAttribute( data, itemSize );
|
||||
|
||||
|
||||
};
|
||||
|
||||
THREE.Int16Attribute = function ( data, itemSize ) {
|
||||
|
||||
console.warn( 'THREE.Int16Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' );
|
||||
return new THREE.BufferAttribute( data, itemSize );
|
||||
|
||||
};
|
||||
|
||||
THREE.Uint16Attribute = function ( data, itemSize ) {
|
||||
|
||||
console.warn( 'THREE.Uint16Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' );
|
||||
return new THREE.BufferAttribute( data, itemSize );
|
||||
|
||||
};
|
||||
|
||||
THREE.Int32Attribute = function ( data, itemSize ) {
|
||||
|
||||
console.warn( 'THREE.Int32Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' );
|
||||
return new THREE.BufferAttribute( data, itemSize );
|
||||
|
||||
};
|
||||
|
||||
THREE.Uint32Attribute = function ( data, itemSize ) {
|
||||
|
||||
console.warn( 'THREE.Uint32Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' );
|
||||
return new THREE.BufferAttribute( data, itemSize );
|
||||
|
||||
};
|
||||
|
||||
THREE.Float32Attribute = function ( data, itemSize ) {
|
||||
|
||||
console.warn( 'THREE.Float32Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' );
|
||||
return new THREE.BufferAttribute( data, itemSize );
|
||||
|
||||
};
|
||||
|
||||
THREE.Float64Attribute = function ( data, itemSize ) {
|
||||
|
||||
console.warn( 'THREE.Float64Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' );
|
||||
return new THREE.BufferAttribute( data, itemSize );
|
||||
|
||||
};
|
||||
|
|
@ -1,964 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.BufferGeometry = function () {
|
||||
|
||||
this.id = THREE.GeometryIdCount ++;
|
||||
this.uuid = THREE.Math.generateUUID();
|
||||
|
||||
this.name = '';
|
||||
|
||||
this.attributes = {};
|
||||
this.drawcalls = [];
|
||||
this.offsets = this.drawcalls; // backwards compatibility
|
||||
|
||||
this.boundingBox = null;
|
||||
this.boundingSphere = null;
|
||||
|
||||
};
|
||||
|
||||
THREE.BufferGeometry.prototype = {
|
||||
|
||||
constructor: THREE.BufferGeometry,
|
||||
|
||||
addAttribute: function ( name, attribute ) {
|
||||
|
||||
if ( attribute instanceof THREE.BufferAttribute === false ) {
|
||||
|
||||
console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
|
||||
|
||||
this.attributes[ name ] = { array: arguments[ 1 ], itemSize: arguments[ 2 ] };
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
this.attributes[ name ] = attribute;
|
||||
|
||||
},
|
||||
|
||||
getAttribute: function ( name ) {
|
||||
|
||||
return this.attributes[ name ];
|
||||
|
||||
},
|
||||
|
||||
addDrawCall: function ( start, count, indexOffset ) {
|
||||
|
||||
this.drawcalls.push( {
|
||||
|
||||
start: start,
|
||||
count: count,
|
||||
index: indexOffset !== undefined ? indexOffset : 0
|
||||
|
||||
} );
|
||||
|
||||
},
|
||||
|
||||
applyMatrix: function ( matrix ) {
|
||||
|
||||
var position = this.attributes.position;
|
||||
|
||||
if ( position !== undefined ) {
|
||||
|
||||
matrix.applyToVector3Array( position.array );
|
||||
position.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
var normal = this.attributes.normal;
|
||||
|
||||
if ( normal !== undefined ) {
|
||||
|
||||
var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
|
||||
|
||||
normalMatrix.applyToVector3Array( normal.array );
|
||||
normal.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
fromGeometry: function ( geometry, settings ) {
|
||||
|
||||
settings = settings || { 'vertexColors': THREE.NoColors };
|
||||
|
||||
var vertices = geometry.vertices;
|
||||
var faces = geometry.faces;
|
||||
var faceVertexUvs = geometry.faceVertexUvs;
|
||||
var vertexColors = settings.vertexColors;
|
||||
var hasFaceVertexUv = faceVertexUvs[ 0 ].length > 0;
|
||||
var hasFaceVertexNormals = faces[ 0 ].vertexNormals.length == 3;
|
||||
|
||||
var positions = new Float32Array( faces.length * 3 * 3 );
|
||||
this.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
|
||||
|
||||
var normals = new Float32Array( faces.length * 3 * 3 );
|
||||
this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
|
||||
|
||||
if ( vertexColors !== THREE.NoColors ) {
|
||||
|
||||
var colors = new Float32Array( faces.length * 3 * 3 );
|
||||
this.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
|
||||
|
||||
}
|
||||
|
||||
if ( hasFaceVertexUv === true ) {
|
||||
|
||||
var uvs = new Float32Array( faces.length * 3 * 2 );
|
||||
this.addAttribute( 'uvs', new THREE.BufferAttribute( uvs, 2 ) );
|
||||
|
||||
}
|
||||
|
||||
for ( var i = 0, i2 = 0, i3 = 0; i < faces.length; i ++, i2 += 6, i3 += 9 ) {
|
||||
|
||||
var face = faces[ i ];
|
||||
|
||||
var a = vertices[ face.a ];
|
||||
var b = vertices[ face.b ];
|
||||
var c = vertices[ face.c ];
|
||||
|
||||
positions[ i3 ] = a.x;
|
||||
positions[ i3 + 1 ] = a.y;
|
||||
positions[ i3 + 2 ] = a.z;
|
||||
|
||||
positions[ i3 + 3 ] = b.x;
|
||||
positions[ i3 + 4 ] = b.y;
|
||||
positions[ i3 + 5 ] = b.z;
|
||||
|
||||
positions[ i3 + 6 ] = c.x;
|
||||
positions[ i3 + 7 ] = c.y;
|
||||
positions[ i3 + 8 ] = c.z;
|
||||
|
||||
if ( hasFaceVertexNormals === true ) {
|
||||
|
||||
var na = face.vertexNormals[ 0 ];
|
||||
var nb = face.vertexNormals[ 1 ];
|
||||
var nc = face.vertexNormals[ 2 ];
|
||||
|
||||
normals[ i3 ] = na.x;
|
||||
normals[ i3 + 1 ] = na.y;
|
||||
normals[ i3 + 2 ] = na.z;
|
||||
|
||||
normals[ i3 + 3 ] = nb.x;
|
||||
normals[ i3 + 4 ] = nb.y;
|
||||
normals[ i3 + 5 ] = nb.z;
|
||||
|
||||
normals[ i3 + 6 ] = nc.x;
|
||||
normals[ i3 + 7 ] = nc.y;
|
||||
normals[ i3 + 8 ] = nc.z;
|
||||
|
||||
} else {
|
||||
|
||||
var n = face.normal;
|
||||
|
||||
normals[ i3 ] = n.x;
|
||||
normals[ i3 + 1 ] = n.y;
|
||||
normals[ i3 + 2 ] = n.z;
|
||||
|
||||
normals[ i3 + 3 ] = n.x;
|
||||
normals[ i3 + 4 ] = n.y;
|
||||
normals[ i3 + 5 ] = n.z;
|
||||
|
||||
normals[ i3 + 6 ] = n.x;
|
||||
normals[ i3 + 7 ] = n.y;
|
||||
normals[ i3 + 8 ] = n.z;
|
||||
|
||||
}
|
||||
|
||||
if ( vertexColors === THREE.FaceColors ) {
|
||||
|
||||
var fc = face.color;
|
||||
|
||||
colors[ i3 ] = fc.r;
|
||||
colors[ i3 + 1 ] = fc.g;
|
||||
colors[ i3 + 2 ] = fc.b;
|
||||
|
||||
colors[ i3 + 3 ] = fc.r;
|
||||
colors[ i3 + 4 ] = fc.g;
|
||||
colors[ i3 + 5 ] = fc.b;
|
||||
|
||||
colors[ i3 + 6 ] = fc.r;
|
||||
colors[ i3 + 7 ] = fc.g;
|
||||
colors[ i3 + 8 ] = fc.b;
|
||||
|
||||
} else if ( vertexColors === THREE.VertexColors ) {
|
||||
|
||||
var vca = face.vertexColors[ 0 ];
|
||||
var vcb = face.vertexColors[ 1 ];
|
||||
var vcc = face.vertexColors[ 2 ];
|
||||
|
||||
colors[ i3 ] = vca.r;
|
||||
colors[ i3 + 1 ] = vca.g;
|
||||
colors[ i3 + 2 ] = vca.b;
|
||||
|
||||
colors[ i3 + 3 ] = vcb.r;
|
||||
colors[ i3 + 4 ] = vcb.g;
|
||||
colors[ i3 + 5 ] = vcb.b;
|
||||
|
||||
colors[ i3 + 6 ] = vcc.r;
|
||||
colors[ i3 + 7 ] = vcc.g;
|
||||
colors[ i3 + 8 ] = vcc.b;
|
||||
|
||||
}
|
||||
|
||||
if ( hasFaceVertexUv === true ) {
|
||||
|
||||
var uva = faceVertexUvs[ 0 ][ i ][ 0 ];
|
||||
var uvb = faceVertexUvs[ 0 ][ i ][ 1 ];
|
||||
var uvc = faceVertexUvs[ 0 ][ i ][ 2 ];
|
||||
|
||||
uvs[ i2 ] = uva.x;
|
||||
uvs[ i2 + 1 ] = uva.y;
|
||||
|
||||
uvs[ i2 + 2 ] = uvb.x;
|
||||
uvs[ i2 + 3 ] = uvb.y;
|
||||
|
||||
uvs[ i2 + 4 ] = uvc.x;
|
||||
uvs[ i2 + 5 ] = uvc.y;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.computeBoundingSphere()
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
computeBoundingBox: function () {
|
||||
|
||||
if ( this.boundingBox === null ) {
|
||||
|
||||
this.boundingBox = new THREE.Box3();
|
||||
|
||||
}
|
||||
|
||||
var positions = this.attributes[ 'position' ].array;
|
||||
|
||||
if ( positions ) {
|
||||
|
||||
var bb = this.boundingBox;
|
||||
|
||||
if ( positions.length >= 3 ) {
|
||||
bb.min.x = bb.max.x = positions[ 0 ];
|
||||
bb.min.y = bb.max.y = positions[ 1 ];
|
||||
bb.min.z = bb.max.z = positions[ 2 ];
|
||||
}
|
||||
|
||||
for ( var i = 3, il = positions.length; i < il; i += 3 ) {
|
||||
|
||||
var x = positions[ i ];
|
||||
var y = positions[ i + 1 ];
|
||||
var z = positions[ i + 2 ];
|
||||
|
||||
// bounding box
|
||||
|
||||
if ( x < bb.min.x ) {
|
||||
|
||||
bb.min.x = x;
|
||||
|
||||
} else if ( x > bb.max.x ) {
|
||||
|
||||
bb.max.x = x;
|
||||
|
||||
}
|
||||
|
||||
if ( y < bb.min.y ) {
|
||||
|
||||
bb.min.y = y;
|
||||
|
||||
} else if ( y > bb.max.y ) {
|
||||
|
||||
bb.max.y = y;
|
||||
|
||||
}
|
||||
|
||||
if ( z < bb.min.z ) {
|
||||
|
||||
bb.min.z = z;
|
||||
|
||||
} else if ( z > bb.max.z ) {
|
||||
|
||||
bb.max.z = z;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( positions === undefined || positions.length === 0 ) {
|
||||
|
||||
this.boundingBox.min.set( 0, 0, 0 );
|
||||
this.boundingBox.max.set( 0, 0, 0 );
|
||||
|
||||
}
|
||||
|
||||
if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
|
||||
|
||||
console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.' );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
computeBoundingSphere: function () {
|
||||
|
||||
var box = new THREE.Box3();
|
||||
var vector = new THREE.Vector3();
|
||||
|
||||
return function () {
|
||||
|
||||
if ( this.boundingSphere === null ) {
|
||||
|
||||
this.boundingSphere = new THREE.Sphere();
|
||||
|
||||
}
|
||||
|
||||
var positions = this.attributes[ 'position' ].array;
|
||||
|
||||
if ( positions ) {
|
||||
|
||||
box.makeEmpty();
|
||||
|
||||
var center = this.boundingSphere.center;
|
||||
|
||||
for ( var i = 0, il = positions.length; i < il; i += 3 ) {
|
||||
|
||||
vector.set( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
|
||||
box.expandByPoint( vector );
|
||||
|
||||
}
|
||||
|
||||
box.center( center );
|
||||
|
||||
// hoping to find a boundingSphere with a radius smaller than the
|
||||
// boundingSphere of the boundingBox: sqrt(3) smaller in the best case
|
||||
|
||||
var maxRadiusSq = 0;
|
||||
|
||||
for ( var i = 0, il = positions.length; i < il; i += 3 ) {
|
||||
|
||||
vector.set( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
|
||||
maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
|
||||
|
||||
}
|
||||
|
||||
this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
|
||||
|
||||
if ( isNaN( this.boundingSphere.radius ) ) {
|
||||
|
||||
console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}(),
|
||||
|
||||
computeFaceNormals: function () {
|
||||
|
||||
// backwards compatibility
|
||||
|
||||
},
|
||||
|
||||
computeVertexNormals: function () {
|
||||
|
||||
if ( this.attributes[ 'position' ] ) {
|
||||
|
||||
var i, il;
|
||||
var j, jl;
|
||||
|
||||
var nVertexElements = this.attributes[ 'position' ].array.length;
|
||||
|
||||
if ( this.attributes[ 'normal' ] === undefined ) {
|
||||
|
||||
this.attributes[ 'normal' ] = {
|
||||
|
||||
itemSize: 3,
|
||||
array: new Float32Array( nVertexElements )
|
||||
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
// reset existing normals to zero
|
||||
|
||||
for ( i = 0, il = this.attributes[ 'normal' ].array.length; i < il; i ++ ) {
|
||||
|
||||
this.attributes[ 'normal' ].array[ i ] = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var positions = this.attributes[ 'position' ].array;
|
||||
var normals = this.attributes[ 'normal' ].array;
|
||||
|
||||
var vA, vB, vC, x, y, z,
|
||||
|
||||
pA = new THREE.Vector3(),
|
||||
pB = new THREE.Vector3(),
|
||||
pC = new THREE.Vector3(),
|
||||
|
||||
cb = new THREE.Vector3(),
|
||||
ab = new THREE.Vector3();
|
||||
|
||||
// indexed elements
|
||||
|
||||
if ( this.attributes[ 'index' ] ) {
|
||||
|
||||
var indices = this.attributes[ 'index' ].array;
|
||||
|
||||
var offsets = ( this.offsets.length > 0 ? this.offsets : [ { start: 0, count: indices.length, index: 0 } ] );
|
||||
|
||||
for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
|
||||
|
||||
var start = offsets[ j ].start;
|
||||
var count = offsets[ j ].count;
|
||||
var index = offsets[ j ].index;
|
||||
|
||||
for ( i = start, il = start + count; i < il; i += 3 ) {
|
||||
|
||||
vA = index + indices[ i ];
|
||||
vB = index + indices[ i + 1 ];
|
||||
vC = index + indices[ i + 2 ];
|
||||
|
||||
x = positions[ vA * 3 ];
|
||||
y = positions[ vA * 3 + 1 ];
|
||||
z = positions[ vA * 3 + 2 ];
|
||||
pA.set( x, y, z );
|
||||
|
||||
x = positions[ vB * 3 ];
|
||||
y = positions[ vB * 3 + 1 ];
|
||||
z = positions[ vB * 3 + 2 ];
|
||||
pB.set( x, y, z );
|
||||
|
||||
x = positions[ vC * 3 ];
|
||||
y = positions[ vC * 3 + 1 ];
|
||||
z = positions[ vC * 3 + 2 ];
|
||||
pC.set( x, y, z );
|
||||
|
||||
cb.subVectors( pC, pB );
|
||||
ab.subVectors( pA, pB );
|
||||
cb.cross( ab );
|
||||
|
||||
normals[ vA * 3 ] += cb.x;
|
||||
normals[ vA * 3 + 1 ] += cb.y;
|
||||
normals[ vA * 3 + 2 ] += cb.z;
|
||||
|
||||
normals[ vB * 3 ] += cb.x;
|
||||
normals[ vB * 3 + 1 ] += cb.y;
|
||||
normals[ vB * 3 + 2 ] += cb.z;
|
||||
|
||||
normals[ vC * 3 ] += cb.x;
|
||||
normals[ vC * 3 + 1 ] += cb.y;
|
||||
normals[ vC * 3 + 2 ] += cb.z;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// non-indexed elements (unconnected triangle soup)
|
||||
|
||||
} else {
|
||||
|
||||
for ( i = 0, il = positions.length; i < il; i += 9 ) {
|
||||
|
||||
x = positions[ i ];
|
||||
y = positions[ i + 1 ];
|
||||
z = positions[ i + 2 ];
|
||||
pA.set( x, y, z );
|
||||
|
||||
x = positions[ i + 3 ];
|
||||
y = positions[ i + 4 ];
|
||||
z = positions[ i + 5 ];
|
||||
pB.set( x, y, z );
|
||||
|
||||
x = positions[ i + 6 ];
|
||||
y = positions[ i + 7 ];
|
||||
z = positions[ i + 8 ];
|
||||
pC.set( x, y, z );
|
||||
|
||||
cb.subVectors( pC, pB );
|
||||
ab.subVectors( pA, pB );
|
||||
cb.cross( ab );
|
||||
|
||||
normals[ i ] = cb.x;
|
||||
normals[ i + 1 ] = cb.y;
|
||||
normals[ i + 2 ] = cb.z;
|
||||
|
||||
normals[ i + 3 ] = cb.x;
|
||||
normals[ i + 4 ] = cb.y;
|
||||
normals[ i + 5 ] = cb.z;
|
||||
|
||||
normals[ i + 6 ] = cb.x;
|
||||
normals[ i + 7 ] = cb.y;
|
||||
normals[ i + 8 ] = cb.z;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.normalizeNormals();
|
||||
|
||||
this.normalsNeedUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
computeTangents: function () {
|
||||
|
||||
// based on http://www.terathon.com/code/tangent.html
|
||||
// (per vertex tangents)
|
||||
|
||||
if ( this.attributes[ 'index' ] === undefined ||
|
||||
this.attributes[ 'position' ] === undefined ||
|
||||
this.attributes[ 'normal' ] === undefined ||
|
||||
this.attributes[ 'uv' ] === undefined ) {
|
||||
|
||||
console.warn( 'Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()' );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
var indices = this.attributes[ 'index' ].array;
|
||||
var positions = this.attributes[ 'position' ].array;
|
||||
var normals = this.attributes[ 'normal' ].array;
|
||||
var uvs = this.attributes[ 'uv' ].array;
|
||||
|
||||
var nVertices = positions.length / 3;
|
||||
|
||||
if ( this.attributes[ 'tangent' ] === undefined ) {
|
||||
|
||||
var nTangentElements = 4 * nVertices;
|
||||
|
||||
this.attributes[ 'tangent' ] = {
|
||||
|
||||
itemSize: 4,
|
||||
array: new Float32Array( nTangentElements )
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
var tangents = this.attributes[ 'tangent' ].array;
|
||||
|
||||
var tan1 = [], tan2 = [];
|
||||
|
||||
for ( var k = 0; k < nVertices; k ++ ) {
|
||||
|
||||
tan1[ k ] = new THREE.Vector3();
|
||||
tan2[ k ] = new THREE.Vector3();
|
||||
|
||||
}
|
||||
|
||||
var xA, yA, zA,
|
||||
xB, yB, zB,
|
||||
xC, yC, zC,
|
||||
|
||||
uA, vA,
|
||||
uB, vB,
|
||||
uC, vC,
|
||||
|
||||
x1, x2, y1, y2, z1, z2,
|
||||
s1, s2, t1, t2, r;
|
||||
|
||||
var sdir = new THREE.Vector3(), tdir = new THREE.Vector3();
|
||||
|
||||
function handleTriangle( a, b, c ) {
|
||||
|
||||
xA = positions[ a * 3 ];
|
||||
yA = positions[ a * 3 + 1 ];
|
||||
zA = positions[ a * 3 + 2 ];
|
||||
|
||||
xB = positions[ b * 3 ];
|
||||
yB = positions[ b * 3 + 1 ];
|
||||
zB = positions[ b * 3 + 2 ];
|
||||
|
||||
xC = positions[ c * 3 ];
|
||||
yC = positions[ c * 3 + 1 ];
|
||||
zC = positions[ c * 3 + 2 ];
|
||||
|
||||
uA = uvs[ a * 2 ];
|
||||
vA = uvs[ a * 2 + 1 ];
|
||||
|
||||
uB = uvs[ b * 2 ];
|
||||
vB = uvs[ b * 2 + 1 ];
|
||||
|
||||
uC = uvs[ c * 2 ];
|
||||
vC = uvs[ c * 2 + 1 ];
|
||||
|
||||
x1 = xB - xA;
|
||||
x2 = xC - xA;
|
||||
|
||||
y1 = yB - yA;
|
||||
y2 = yC - yA;
|
||||
|
||||
z1 = zB - zA;
|
||||
z2 = zC - zA;
|
||||
|
||||
s1 = uB - uA;
|
||||
s2 = uC - uA;
|
||||
|
||||
t1 = vB - vA;
|
||||
t2 = vC - vA;
|
||||
|
||||
r = 1.0 / ( s1 * t2 - s2 * t1 );
|
||||
|
||||
sdir.set(
|
||||
( t2 * x1 - t1 * x2 ) * r,
|
||||
( t2 * y1 - t1 * y2 ) * r,
|
||||
( t2 * z1 - t1 * z2 ) * r
|
||||
);
|
||||
|
||||
tdir.set(
|
||||
( s1 * x2 - s2 * x1 ) * r,
|
||||
( s1 * y2 - s2 * y1 ) * r,
|
||||
( s1 * z2 - s2 * z1 ) * r
|
||||
);
|
||||
|
||||
tan1[ a ].add( sdir );
|
||||
tan1[ b ].add( sdir );
|
||||
tan1[ c ].add( sdir );
|
||||
|
||||
tan2[ a ].add( tdir );
|
||||
tan2[ b ].add( tdir );
|
||||
tan2[ c ].add( tdir );
|
||||
|
||||
}
|
||||
|
||||
var i, il;
|
||||
var j, jl;
|
||||
var iA, iB, iC;
|
||||
|
||||
var offsets = this.offsets;
|
||||
|
||||
for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
|
||||
|
||||
var start = offsets[ j ].start;
|
||||
var count = offsets[ j ].count;
|
||||
var index = offsets[ j ].index;
|
||||
|
||||
for ( i = start, il = start + count; i < il; i += 3 ) {
|
||||
|
||||
iA = index + indices[ i ];
|
||||
iB = index + indices[ i + 1 ];
|
||||
iC = index + indices[ i + 2 ];
|
||||
|
||||
handleTriangle( iA, iB, iC );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3();
|
||||
var n = new THREE.Vector3(), n2 = new THREE.Vector3();
|
||||
var w, t, test;
|
||||
|
||||
function handleVertex( v ) {
|
||||
|
||||
n.x = normals[ v * 3 ];
|
||||
n.y = normals[ v * 3 + 1 ];
|
||||
n.z = normals[ v * 3 + 2 ];
|
||||
|
||||
n2.copy( n );
|
||||
|
||||
t = tan1[ v ];
|
||||
|
||||
// Gram-Schmidt orthogonalize
|
||||
|
||||
tmp.copy( t );
|
||||
tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
|
||||
|
||||
// Calculate handedness
|
||||
|
||||
tmp2.crossVectors( n2, t );
|
||||
test = tmp2.dot( tan2[ v ] );
|
||||
w = ( test < 0.0 ) ? - 1.0 : 1.0;
|
||||
|
||||
tangents[ v * 4 ] = tmp.x;
|
||||
tangents[ v * 4 + 1 ] = tmp.y;
|
||||
tangents[ v * 4 + 2 ] = tmp.z;
|
||||
tangents[ v * 4 + 3 ] = w;
|
||||
|
||||
}
|
||||
|
||||
for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
|
||||
|
||||
var start = offsets[ j ].start;
|
||||
var count = offsets[ j ].count;
|
||||
var index = offsets[ j ].index;
|
||||
|
||||
for ( i = start, il = start + count; i < il; i += 3 ) {
|
||||
|
||||
iA = index + indices[ i ];
|
||||
iB = index + indices[ i + 1 ];
|
||||
iC = index + indices[ i + 2 ];
|
||||
|
||||
handleVertex( iA );
|
||||
handleVertex( iB );
|
||||
handleVertex( iC );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/*
|
||||
computeOffsets
|
||||
Compute the draw offset for large models by chunking the index buffer into chunks of 65k addressable vertices.
|
||||
This method will effectively rewrite the index buffer and remap all attributes to match the new indices.
|
||||
WARNING: This method will also expand the vertex count to prevent sprawled triangles across draw offsets.
|
||||
indexBufferSize - Defaults to 65535, but allows for larger or smaller chunks.
|
||||
*/
|
||||
computeOffsets: function ( indexBufferSize ) {
|
||||
|
||||
var size = indexBufferSize;
|
||||
if ( indexBufferSize === undefined )
|
||||
size = 65535; //WebGL limits type of index buffer values to 16-bit.
|
||||
|
||||
var s = Date.now();
|
||||
|
||||
var indices = this.attributes[ 'index' ].array;
|
||||
var vertices = this.attributes[ 'position' ].array;
|
||||
|
||||
var verticesCount = ( vertices.length / 3 );
|
||||
var facesCount = ( indices.length / 3 );
|
||||
|
||||
/*
|
||||
console.log("Computing buffers in offsets of "+size+" -> indices:"+indices.length+" vertices:"+vertices.length);
|
||||
console.log("Faces to process: "+(indices.length/3));
|
||||
console.log("Reordering "+verticesCount+" vertices.");
|
||||
*/
|
||||
|
||||
var sortedIndices = new Uint16Array( indices.length ); //16-bit buffers
|
||||
var indexPtr = 0;
|
||||
var vertexPtr = 0;
|
||||
|
||||
var offsets = [ { start:0, count:0, index:0 } ];
|
||||
var offset = offsets[ 0 ];
|
||||
|
||||
var duplicatedVertices = 0;
|
||||
var newVerticeMaps = 0;
|
||||
var faceVertices = new Int32Array( 6 );
|
||||
var vertexMap = new Int32Array( vertices.length );
|
||||
var revVertexMap = new Int32Array( vertices.length );
|
||||
for ( var j = 0; j < vertices.length; j ++ ) { vertexMap[ j ] = - 1; revVertexMap[ j ] = - 1; }
|
||||
|
||||
/*
|
||||
Traverse every face and reorder vertices in the proper offsets of 65k.
|
||||
We can have more than 65k entries in the index buffer per offset, but only reference 65k values.
|
||||
*/
|
||||
for ( var findex = 0; findex < facesCount; findex ++ ) {
|
||||
newVerticeMaps = 0;
|
||||
|
||||
for ( var vo = 0; vo < 3; vo ++ ) {
|
||||
var vid = indices[ findex * 3 + vo ];
|
||||
if ( vertexMap[ vid ] == - 1 ) {
|
||||
//Unmapped vertice
|
||||
faceVertices[ vo * 2 ] = vid;
|
||||
faceVertices[ vo * 2 + 1 ] = - 1;
|
||||
newVerticeMaps ++;
|
||||
} else if ( vertexMap[ vid ] < offset.index ) {
|
||||
//Reused vertices from previous block (duplicate)
|
||||
faceVertices[ vo * 2 ] = vid;
|
||||
faceVertices[ vo * 2 + 1 ] = - 1;
|
||||
duplicatedVertices ++;
|
||||
} else {
|
||||
//Reused vertice in the current block
|
||||
faceVertices[ vo * 2 ] = vid;
|
||||
faceVertices[ vo * 2 + 1 ] = vertexMap[ vid ];
|
||||
}
|
||||
}
|
||||
|
||||
var faceMax = vertexPtr + newVerticeMaps;
|
||||
if ( faceMax > ( offset.index + size ) ) {
|
||||
var new_offset = { start:indexPtr, count:0, index:vertexPtr };
|
||||
offsets.push( new_offset );
|
||||
offset = new_offset;
|
||||
|
||||
//Re-evaluate reused vertices in light of new offset.
|
||||
for ( var v = 0; v < 6; v += 2 ) {
|
||||
var new_vid = faceVertices[ v + 1 ];
|
||||
if ( new_vid > - 1 && new_vid < offset.index )
|
||||
faceVertices[ v + 1 ] = - 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Reindex the face.
|
||||
for ( var v = 0; v < 6; v += 2 ) {
|
||||
var vid = faceVertices[ v ];
|
||||
var new_vid = faceVertices[ v + 1 ];
|
||||
|
||||
if ( new_vid === - 1 )
|
||||
new_vid = vertexPtr ++;
|
||||
|
||||
vertexMap[ vid ] = new_vid;
|
||||
revVertexMap[ new_vid ] = vid;
|
||||
sortedIndices[ indexPtr ++ ] = new_vid - offset.index; //XXX overflows at 16bit
|
||||
offset.count ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move all attribute values to map to the new computed indices , also expand the vertice stack to match our new vertexPtr. */
|
||||
this.reorderBuffers( sortedIndices, revVertexMap, vertexPtr );
|
||||
this.offsets = offsets;
|
||||
|
||||
/*
|
||||
var orderTime = Date.now();
|
||||
console.log("Reorder time: "+(orderTime-s)+"ms");
|
||||
console.log("Duplicated "+duplicatedVertices+" vertices.");
|
||||
console.log("Compute Buffers time: "+(Date.now()-s)+"ms");
|
||||
console.log("Draw offsets: "+offsets.length);
|
||||
*/
|
||||
|
||||
return offsets;
|
||||
},
|
||||
|
||||
merge: function () {
|
||||
|
||||
console.log( 'BufferGeometry.merge(): TODO' );
|
||||
|
||||
},
|
||||
|
||||
normalizeNormals: function () {
|
||||
|
||||
var normals = this.attributes[ 'normal' ].array;
|
||||
|
||||
var x, y, z, n;
|
||||
|
||||
for ( var i = 0, il = normals.length; i < il; i += 3 ) {
|
||||
|
||||
x = normals[ i ];
|
||||
y = normals[ i + 1 ];
|
||||
z = normals[ i + 2 ];
|
||||
|
||||
n = 1.0 / Math.sqrt( x * x + y * y + z * z );
|
||||
|
||||
normals[ i ] *= n;
|
||||
normals[ i + 1 ] *= n;
|
||||
normals[ i + 2 ] *= n;
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/*
|
||||
reoderBuffers:
|
||||
Reorder attributes based on a new indexBuffer and indexMap.
|
||||
indexBuffer - Uint16Array of the new ordered indices.
|
||||
indexMap - Int32Array where the position is the new vertex ID and the value the old vertex ID for each vertex.
|
||||
vertexCount - Amount of total vertices considered in this reordering (in case you want to grow the vertice stack).
|
||||
*/
|
||||
reorderBuffers: function ( indexBuffer, indexMap, vertexCount ) {
|
||||
|
||||
/* Create a copy of all attributes for reordering. */
|
||||
var sortedAttributes = {};
|
||||
var types = [ Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];
|
||||
for ( var attr in this.attributes ) {
|
||||
if ( attr == 'index' )
|
||||
continue;
|
||||
var sourceArray = this.attributes[ attr ].array;
|
||||
for ( var i = 0, il = types.length; i < il; i ++ ) {
|
||||
var type = types[ i ];
|
||||
if ( sourceArray instanceof type ) {
|
||||
sortedAttributes[ attr ] = new type( this.attributes[ attr ].itemSize * vertexCount );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Move attribute positions based on the new index map */
|
||||
for ( var new_vid = 0; new_vid < vertexCount; new_vid ++ ) {
|
||||
var vid = indexMap[ new_vid ];
|
||||
for ( var attr in this.attributes ) {
|
||||
if ( attr == 'index' )
|
||||
continue;
|
||||
var attrArray = this.attributes[ attr ].array;
|
||||
var attrSize = this.attributes[ attr ].itemSize;
|
||||
var sortedAttr = sortedAttributes[ attr ];
|
||||
for ( var k = 0; k < attrSize; k ++ )
|
||||
sortedAttr[ new_vid * attrSize + k ] = attrArray[ vid * attrSize + k ];
|
||||
}
|
||||
}
|
||||
|
||||
/* Carry the new sorted buffers locally */
|
||||
this.attributes[ 'index' ].array = indexBuffer;
|
||||
for ( var attr in this.attributes ) {
|
||||
if ( attr == 'index' )
|
||||
continue;
|
||||
this.attributes[ attr ].array = sortedAttributes[ attr ];
|
||||
this.attributes[ attr ].numItems = this.attributes[ attr ].itemSize * vertexCount;
|
||||
}
|
||||
},
|
||||
|
||||
clone: function () {
|
||||
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
|
||||
var types = [ Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];
|
||||
|
||||
for ( var attr in this.attributes ) {
|
||||
|
||||
var sourceAttr = this.attributes[ attr ];
|
||||
var sourceArray = sourceAttr.array;
|
||||
|
||||
var attribute = {
|
||||
|
||||
itemSize: sourceAttr.itemSize,
|
||||
array: null
|
||||
|
||||
};
|
||||
|
||||
for ( var i = 0, il = types.length; i < il; i ++ ) {
|
||||
|
||||
var type = types[ i ];
|
||||
|
||||
if ( sourceArray instanceof type ) {
|
||||
|
||||
attribute.array = new type( sourceArray );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.attributes[ attr ] = attribute;
|
||||
|
||||
}
|
||||
|
||||
for ( var i = 0, il = this.offsets.length; i < il; i ++ ) {
|
||||
|
||||
var offset = this.offsets[ i ];
|
||||
|
||||
geometry.offsets.push( {
|
||||
|
||||
start: offset.start,
|
||||
index: offset.index,
|
||||
count: offset.count
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
return geometry;
|
||||
|
||||
},
|
||||
|
||||
dispose: function () {
|
||||
|
||||
this.dispatchEvent( { type: 'dispose' } );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.EventDispatcher.prototype.apply( THREE.BufferGeometry.prototype );
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.Clock = function ( autoStart ) {
|
||||
|
||||
this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
|
||||
|
||||
this.startTime = 0;
|
||||
this.oldTime = 0;
|
||||
this.elapsedTime = 0;
|
||||
|
||||
this.running = false;
|
||||
|
||||
};
|
||||
|
||||
THREE.Clock.prototype = {
|
||||
|
||||
constructor: THREE.Clock,
|
||||
|
||||
start: function () {
|
||||
|
||||
this.startTime = self.performance !== undefined && self.performance.now !== undefined
|
||||
? self.performance.now()
|
||||
: Date.now();
|
||||
|
||||
this.oldTime = this.startTime;
|
||||
this.running = true;
|
||||
},
|
||||
|
||||
stop: function () {
|
||||
|
||||
this.getElapsedTime();
|
||||
this.running = false;
|
||||
|
||||
},
|
||||
|
||||
getElapsedTime: function () {
|
||||
|
||||
this.getDelta();
|
||||
return this.elapsedTime;
|
||||
|
||||
},
|
||||
|
||||
getDelta: function () {
|
||||
|
||||
var diff = 0;
|
||||
|
||||
if ( this.autoStart && ! this.running ) {
|
||||
|
||||
this.start();
|
||||
|
||||
}
|
||||
|
||||
if ( this.running ) {
|
||||
|
||||
var newTime = self.performance !== undefined && self.performance.now !== undefined
|
||||
? self.performance.now()
|
||||
: Date.now();
|
||||
|
||||
diff = 0.001 * ( newTime - this.oldTime );
|
||||
this.oldTime = newTime;
|
||||
|
||||
this.elapsedTime += diff;
|
||||
|
||||
}
|
||||
|
||||
return diff;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
/**
|
||||
* https://github.com/mrdoob/eventdispatcher.js/
|
||||
*/
|
||||
|
||||
THREE.EventDispatcher = function () {}
|
||||
|
||||
THREE.EventDispatcher.prototype = {
|
||||
|
||||
constructor: THREE.EventDispatcher,
|
||||
|
||||
apply: function ( object ) {
|
||||
|
||||
object.addEventListener = THREE.EventDispatcher.prototype.addEventListener;
|
||||
object.hasEventListener = THREE.EventDispatcher.prototype.hasEventListener;
|
||||
object.removeEventListener = THREE.EventDispatcher.prototype.removeEventListener;
|
||||
object.dispatchEvent = THREE.EventDispatcher.prototype.dispatchEvent;
|
||||
|
||||
},
|
||||
|
||||
addEventListener: function ( type, listener ) {
|
||||
|
||||
if ( this._listeners === undefined ) this._listeners = {};
|
||||
|
||||
var listeners = this._listeners;
|
||||
|
||||
if ( listeners[ type ] === undefined ) {
|
||||
|
||||
listeners[ type ] = [];
|
||||
|
||||
}
|
||||
|
||||
if ( listeners[ type ].indexOf( listener ) === - 1 ) {
|
||||
|
||||
listeners[ type ].push( listener );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
hasEventListener: function ( type, listener ) {
|
||||
|
||||
if ( this._listeners === undefined ) return false;
|
||||
|
||||
var listeners = this._listeners;
|
||||
|
||||
if ( listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1 ) {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
},
|
||||
|
||||
removeEventListener: function ( type, listener ) {
|
||||
|
||||
if ( this._listeners === undefined ) return;
|
||||
|
||||
var listeners = this._listeners;
|
||||
var listenerArray = listeners[ type ];
|
||||
|
||||
if ( listenerArray !== undefined ) {
|
||||
|
||||
var index = listenerArray.indexOf( listener );
|
||||
|
||||
if ( index !== - 1 ) {
|
||||
|
||||
listenerArray.splice( index, 1 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
dispatchEvent: function ( event ) {
|
||||
|
||||
if ( this._listeners === undefined ) return;
|
||||
|
||||
var listeners = this._listeners;
|
||||
var listenerArray = listeners[ event.type ];
|
||||
|
||||
if ( listenerArray !== undefined ) {
|
||||
|
||||
event.target = this;
|
||||
|
||||
var array = [];
|
||||
var length = listenerArray.length;
|
||||
|
||||
for ( var i = 0; i < length; i ++ ) {
|
||||
|
||||
array[ i ] = listenerArray[ i ];
|
||||
|
||||
}
|
||||
|
||||
for ( var i = 0; i < length; i ++ ) {
|
||||
|
||||
array[ i ].call( this, event );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.Face3 = function ( a, b, c, normal, color, materialIndex ) {
|
||||
|
||||
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.materialIndex = materialIndex !== undefined ? materialIndex : 0;
|
||||
|
||||
};
|
||||
|
||||
THREE.Face3.prototype = {
|
||||
|
||||
constructor: THREE.Face3,
|
||||
|
||||
clone: function () {
|
||||
|
||||
var face = new THREE.Face3( this.a, this.b, this.c );
|
||||
|
||||
face.normal.copy( this.normal );
|
||||
face.color.copy( this.color );
|
||||
|
||||
face.materialIndex = this.materialIndex;
|
||||
|
||||
for ( var i = 0, il = this.vertexNormals.length; i < il; i ++ ) {
|
||||
|
||||
face.vertexNormals[ i ] = this.vertexNormals[ i ].clone();
|
||||
|
||||
}
|
||||
|
||||
for ( var i = 0, il = this.vertexColors.length; i < il; i ++ ) {
|
||||
|
||||
face.vertexColors[ i ] = this.vertexColors[ i ].clone();
|
||||
|
||||
}
|
||||
|
||||
for ( var i = 0, il = this.vertexTangents.length; i < il; i ++ ) {
|
||||
|
||||
face.vertexTangents[ i ] = this.vertexTangents[ i ].clone();
|
||||
|
||||
}
|
||||
|
||||
return face;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.Face4 = function ( a, b, c, d, normal, color, materialIndex ) {
|
||||
|
||||
console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' )
|
||||
return new THREE.Face3( a, b, c, normal, color, materialIndex );
|
||||
|
||||
};
|
||||
|
|
@ -1,784 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author kile / http://kile.stravaganza.org/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
* @author mikael emtinger / http://gomo.se/
|
||||
* @author zz85 / http://www.lab4games.net/zz85/blog
|
||||
* @author bhouston / http://exocortex.com
|
||||
*/
|
||||
|
||||
THREE.Geometry = function () {
|
||||
|
||||
this.id = THREE.GeometryIdCount ++;
|
||||
this.uuid = THREE.Math.generateUUID();
|
||||
|
||||
this.name = '';
|
||||
|
||||
this.vertices = [];
|
||||
this.colors = []; // one-to-one vertex colors, used in Points and Line
|
||||
|
||||
this.faces = [];
|
||||
|
||||
this.faceVertexUvs = [ [] ];
|
||||
|
||||
this.morphTargets = [];
|
||||
this.morphColors = [];
|
||||
this.morphNormals = [];
|
||||
|
||||
this.skinWeights = [];
|
||||
this.skinIndices = [];
|
||||
|
||||
this.lineDistances = [];
|
||||
|
||||
this.boundingBox = null;
|
||||
this.boundingSphere = null;
|
||||
|
||||
this.hasTangents = false;
|
||||
|
||||
this.dynamic = true; // the intermediate typed arrays will be deleted when set to false
|
||||
|
||||
// update flags
|
||||
|
||||
this.verticesNeedUpdate = false;
|
||||
this.elementsNeedUpdate = false;
|
||||
this.uvsNeedUpdate = false;
|
||||
this.normalsNeedUpdate = false;
|
||||
this.tangentsNeedUpdate = false;
|
||||
this.colorsNeedUpdate = false;
|
||||
this.lineDistancesNeedUpdate = false;
|
||||
|
||||
this.buffersNeedUpdate = false;
|
||||
this.groupsNeedUpdate = false;
|
||||
|
||||
};
|
||||
|
||||
THREE.Geometry.prototype = {
|
||||
|
||||
constructor: THREE.Geometry,
|
||||
|
||||
applyMatrix: function ( matrix ) {
|
||||
|
||||
var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
|
||||
|
||||
for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
|
||||
|
||||
var vertex = this.vertices[ i ];
|
||||
vertex.applyMatrix4( matrix );
|
||||
|
||||
}
|
||||
|
||||
for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
|
||||
|
||||
var face = this.faces[ i ];
|
||||
face.normal.applyMatrix3( normalMatrix ).normalize();
|
||||
|
||||
for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
|
||||
|
||||
face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( this.boundingBox instanceof THREE.Box3 ) {
|
||||
|
||||
this.computeBoundingBox();
|
||||
|
||||
}
|
||||
|
||||
if ( this.boundingSphere instanceof THREE.Sphere ) {
|
||||
|
||||
this.computeBoundingSphere();
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
center: function () {
|
||||
|
||||
this.computeBoundingBox();
|
||||
|
||||
var offset = new THREE.Vector3();
|
||||
|
||||
offset.addVectors( this.boundingBox.min, this.boundingBox.max );
|
||||
offset.multiplyScalar( - 0.5 );
|
||||
|
||||
this.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) );
|
||||
this.computeBoundingBox();
|
||||
|
||||
return offset;
|
||||
|
||||
},
|
||||
|
||||
computeFaceNormals: function () {
|
||||
|
||||
var cb = new THREE.Vector3(), ab = new THREE.Vector3();
|
||||
|
||||
for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
||||
|
||||
var face = this.faces[ f ];
|
||||
|
||||
var vA = this.vertices[ face.a ];
|
||||
var vB = this.vertices[ face.b ];
|
||||
var vC = this.vertices[ face.c ];
|
||||
|
||||
cb.subVectors( vC, vB );
|
||||
ab.subVectors( vA, vB );
|
||||
cb.cross( ab );
|
||||
|
||||
cb.normalize();
|
||||
|
||||
face.normal.copy( cb );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
computeVertexNormals: function ( areaWeighted ) {
|
||||
|
||||
var v, vl, f, fl, face, vertices;
|
||||
|
||||
vertices = new Array( this.vertices.length );
|
||||
|
||||
for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
|
||||
|
||||
vertices[ v ] = new THREE.Vector3();
|
||||
|
||||
}
|
||||
|
||||
if ( areaWeighted ) {
|
||||
|
||||
// vertex normals weighted by triangle areas
|
||||
// http://www.iquilezles.org/www/articles/normals/normals.htm
|
||||
|
||||
var vA, vB, vC, vD;
|
||||
var cb = new THREE.Vector3(), ab = new THREE.Vector3(),
|
||||
db = new THREE.Vector3(), dc = new THREE.Vector3(), bc = new THREE.Vector3();
|
||||
|
||||
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
||||
|
||||
face = this.faces[ f ];
|
||||
|
||||
vA = this.vertices[ face.a ];
|
||||
vB = this.vertices[ face.b ];
|
||||
vC = this.vertices[ face.c ];
|
||||
|
||||
cb.subVectors( vC, vB );
|
||||
ab.subVectors( vA, vB );
|
||||
cb.cross( ab );
|
||||
|
||||
vertices[ face.a ].add( cb );
|
||||
vertices[ face.b ].add( cb );
|
||||
vertices[ face.c ].add( cb );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
||||
|
||||
face = this.faces[ f ];
|
||||
|
||||
vertices[ face.a ].add( face.normal );
|
||||
vertices[ face.b ].add( face.normal );
|
||||
vertices[ face.c ].add( 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 ];
|
||||
|
||||
face.vertexNormals[ 0 ] = vertices[ face.a ].clone();
|
||||
face.vertexNormals[ 1 ] = vertices[ face.b ].clone();
|
||||
face.vertexNormals[ 2 ] = vertices[ face.c ].clone();
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
computeMorphNormals: function () {
|
||||
|
||||
var i, il, f, fl, face;
|
||||
|
||||
// save original normals
|
||||
// - create temp variables on first access
|
||||
// otherwise just copy (for faster repeated calls)
|
||||
|
||||
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
||||
|
||||
face = this.faces[ f ];
|
||||
|
||||
if ( ! face.__originalFaceNormal ) {
|
||||
|
||||
face.__originalFaceNormal = face.normal.clone();
|
||||
|
||||
} else {
|
||||
|
||||
face.__originalFaceNormal.copy( face.normal );
|
||||
|
||||
}
|
||||
|
||||
if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
|
||||
|
||||
for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
|
||||
|
||||
if ( ! face.__originalVertexNormals[ i ] ) {
|
||||
|
||||
face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
|
||||
|
||||
} else {
|
||||
|
||||
face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// use temp geometry to compute face and vertex normals for each morph
|
||||
|
||||
var tmpGeo = new THREE.Geometry();
|
||||
tmpGeo.faces = this.faces;
|
||||
|
||||
for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
|
||||
|
||||
// create on first access
|
||||
|
||||
if ( ! this.morphNormals[ i ] ) {
|
||||
|
||||
this.morphNormals[ i ] = {};
|
||||
this.morphNormals[ i ].faceNormals = [];
|
||||
this.morphNormals[ i ].vertexNormals = [];
|
||||
|
||||
var dstNormalsFace = this.morphNormals[ i ].faceNormals;
|
||||
var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
|
||||
|
||||
var faceNormal, vertexNormals;
|
||||
|
||||
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
||||
|
||||
faceNormal = new THREE.Vector3();
|
||||
vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
|
||||
|
||||
dstNormalsFace.push( faceNormal );
|
||||
dstNormalsVertex.push( vertexNormals );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var morphNormals = this.morphNormals[ i ];
|
||||
|
||||
// set vertices to morph target
|
||||
|
||||
tmpGeo.vertices = this.morphTargets[ i ].vertices;
|
||||
|
||||
// compute morph normals
|
||||
|
||||
tmpGeo.computeFaceNormals();
|
||||
tmpGeo.computeVertexNormals();
|
||||
|
||||
// store morph normals
|
||||
|
||||
var faceNormal, vertexNormals;
|
||||
|
||||
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
||||
|
||||
face = this.faces[ f ];
|
||||
|
||||
faceNormal = morphNormals.faceNormals[ f ];
|
||||
vertexNormals = morphNormals.vertexNormals[ f ];
|
||||
|
||||
faceNormal.copy( face.normal );
|
||||
|
||||
vertexNormals.a.copy( face.vertexNormals[ 0 ] );
|
||||
vertexNormals.b.copy( face.vertexNormals[ 1 ] );
|
||||
vertexNormals.c.copy( face.vertexNormals[ 2 ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// restore original normals
|
||||
|
||||
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
||||
|
||||
face = this.faces[ f ];
|
||||
|
||||
face.normal = face.__originalFaceNormal;
|
||||
face.vertexNormals = face.__originalVertexNormals;
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
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 ];
|
||||
vB = context.vertices[ b ];
|
||||
vC = context.vertices[ c ];
|
||||
|
||||
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.x - uvA.x;
|
||||
s2 = uvC.x - uvA.x;
|
||||
t1 = uvB.y - uvA.y;
|
||||
t2 = uvC.y - uvA.y;
|
||||
|
||||
r = 1.0 / ( s1 * t2 - s2 * t1 );
|
||||
sdir.set( ( t2 * x1 - t1 * x2 ) * r,
|
||||
( t2 * y1 - t1 * y2 ) * r,
|
||||
( t2 * z1 - t1 * z2 ) * r );
|
||||
tdir.set( ( s1 * x2 - s2 * x1 ) * r,
|
||||
( s1 * y2 - s2 * y1 ) * r,
|
||||
( s1 * z2 - s2 * z1 ) * r );
|
||||
|
||||
tan1[ a ].add( sdir );
|
||||
tan1[ b ].add( sdir );
|
||||
tan1[ c ].add( sdir );
|
||||
|
||||
tan2[ a ].add( tdir );
|
||||
tan2[ b ].add( tdir );
|
||||
tan2[ c ].add( tdir );
|
||||
|
||||
}
|
||||
|
||||
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
||||
|
||||
face = this.faces[ f ];
|
||||
uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
|
||||
|
||||
handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
|
||||
|
||||
}
|
||||
|
||||
var faceIndex = [ 'a', 'b', 'c', 'd' ];
|
||||
|
||||
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
||||
|
||||
face = this.faces[ f ];
|
||||
|
||||
for ( i = 0; i < Math.min( face.vertexNormals.length, 3 ); i ++ ) {
|
||||
|
||||
n.copy( face.vertexNormals[ i ] );
|
||||
|
||||
vertexIndex = face[ faceIndex[ i ] ];
|
||||
|
||||
t = tan1[ vertexIndex ];
|
||||
|
||||
// Gram-Schmidt orthogonalize
|
||||
|
||||
tmp.copy( t );
|
||||
tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
|
||||
|
||||
// Calculate handedness
|
||||
|
||||
tmp2.crossVectors( 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;
|
||||
|
||||
},
|
||||
|
||||
computeLineDistances: function () {
|
||||
|
||||
var d = 0;
|
||||
var vertices = this.vertices;
|
||||
|
||||
for ( var i = 0, il = vertices.length; i < il; i ++ ) {
|
||||
|
||||
if ( i > 0 ) {
|
||||
|
||||
d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
|
||||
|
||||
}
|
||||
|
||||
this.lineDistances[ i ] = d;
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
computeBoundingBox: function () {
|
||||
|
||||
if ( this.boundingBox === null ) {
|
||||
|
||||
this.boundingBox = new THREE.Box3();
|
||||
|
||||
}
|
||||
|
||||
this.boundingBox.setFromPoints( this.vertices );
|
||||
|
||||
},
|
||||
|
||||
computeBoundingSphere: function () {
|
||||
|
||||
if ( this.boundingSphere === null ) {
|
||||
|
||||
this.boundingSphere = new THREE.Sphere();
|
||||
|
||||
}
|
||||
|
||||
this.boundingSphere.setFromPoints( this.vertices );
|
||||
|
||||
},
|
||||
|
||||
merge: function ( geometry, matrix, materialIndexOffset ) {
|
||||
|
||||
if ( geometry instanceof THREE.Geometry === false ) {
|
||||
|
||||
console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
var normalMatrix,
|
||||
vertexOffset = this.vertices.length,
|
||||
uvPosition = this.faceVertexUvs[ 0 ].length,
|
||||
vertices1 = this.vertices,
|
||||
vertices2 = geometry.vertices,
|
||||
faces1 = this.faces,
|
||||
faces2 = geometry.faces,
|
||||
uvs1 = this.faceVertexUvs[ 0 ],
|
||||
uvs2 = geometry.faceVertexUvs[ 0 ];
|
||||
|
||||
if ( materialIndexOffset === undefined ) materialIndexOffset = 0;
|
||||
|
||||
if ( matrix !== undefined ) {
|
||||
|
||||
normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
|
||||
|
||||
}
|
||||
|
||||
// vertices
|
||||
|
||||
for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
|
||||
|
||||
var vertex = vertices2[ i ];
|
||||
|
||||
var vertexCopy = vertex.clone();
|
||||
|
||||
if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
|
||||
|
||||
vertices1.push( vertexCopy );
|
||||
|
||||
}
|
||||
|
||||
// faces
|
||||
|
||||
for ( i = 0, il = faces2.length; i < il; i ++ ) {
|
||||
|
||||
var face = faces2[ i ], faceCopy, normal, color,
|
||||
faceVertexNormals = face.vertexNormals,
|
||||
faceVertexColors = face.vertexColors;
|
||||
|
||||
faceCopy = new THREE.Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
|
||||
faceCopy.normal.copy( face.normal );
|
||||
|
||||
if ( normalMatrix !== undefined ) {
|
||||
|
||||
faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
|
||||
|
||||
}
|
||||
|
||||
for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
|
||||
|
||||
normal = faceVertexNormals[ j ].clone();
|
||||
|
||||
if ( normalMatrix !== undefined ) {
|
||||
|
||||
normal.applyMatrix3( normalMatrix ).normalize();
|
||||
|
||||
}
|
||||
|
||||
faceCopy.vertexNormals.push( normal );
|
||||
|
||||
}
|
||||
|
||||
faceCopy.color.copy( face.color );
|
||||
|
||||
for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
|
||||
|
||||
color = faceVertexColors[ j ];
|
||||
faceCopy.vertexColors.push( color.clone() );
|
||||
|
||||
}
|
||||
|
||||
faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
|
||||
|
||||
faces1.push( faceCopy );
|
||||
|
||||
}
|
||||
|
||||
// uvs
|
||||
|
||||
for ( i = 0, il = uvs2.length; i < il; i ++ ) {
|
||||
|
||||
var uv = uvs2[ i ], uvCopy = [];
|
||||
|
||||
if ( uv === undefined ) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
|
||||
|
||||
uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );
|
||||
|
||||
}
|
||||
|
||||
uvs1.push( uvCopy );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/*
|
||||
* Checks for duplicate vertices with hashmap.
|
||||
* Duplicated vertices are removed
|
||||
* and faces' vertices are updated.
|
||||
*/
|
||||
|
||||
mergeVertices: function () {
|
||||
|
||||
var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
|
||||
var unique = [], changes = [];
|
||||
|
||||
var v, key;
|
||||
var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
|
||||
var precision = Math.pow( 10, precisionPoints );
|
||||
var i,il, face;
|
||||
var indices, k, j, jl, u;
|
||||
|
||||
for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
|
||||
|
||||
v = this.vertices[ i ];
|
||||
key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
|
||||
|
||||
if ( verticesMap[ key ] === undefined ) {
|
||||
|
||||
verticesMap[ key ] = i;
|
||||
unique.push( this.vertices[ i ] );
|
||||
changes[ i ] = unique.length - 1;
|
||||
|
||||
} else {
|
||||
|
||||
//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
|
||||
changes[ i ] = changes[ verticesMap[ key ] ];
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// if faces are completely degenerate after merging vertices, we
|
||||
// have to remove them from the geometry.
|
||||
var faceIndicesToRemove = [];
|
||||
|
||||
for ( i = 0, il = this.faces.length; i < il; i ++ ) {
|
||||
|
||||
face = this.faces[ i ];
|
||||
|
||||
face.a = changes[ face.a ];
|
||||
face.b = changes[ face.b ];
|
||||
face.c = changes[ face.c ];
|
||||
|
||||
indices = [ face.a, face.b, face.c ];
|
||||
|
||||
var dupIndex = - 1;
|
||||
|
||||
// if any duplicate vertices are found in a Face3
|
||||
// we have to remove the face as nothing can be saved
|
||||
for ( var n = 0; n < 3; n ++ ) {
|
||||
if ( indices[ n ] == indices[ ( n + 1 ) % 3 ] ) {
|
||||
|
||||
dupIndex = n;
|
||||
faceIndicesToRemove.push( i );
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
|
||||
var idx = faceIndicesToRemove[ i ];
|
||||
|
||||
this.faces.splice( idx, 1 );
|
||||
|
||||
for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
|
||||
|
||||
this.faceVertexUvs[ j ].splice( idx, 1 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Use unique set of vertices
|
||||
|
||||
var diff = this.vertices.length - unique.length;
|
||||
this.vertices = unique;
|
||||
return diff;
|
||||
|
||||
},
|
||||
|
||||
// Geometry splitting
|
||||
|
||||
makeGroups: ( function () {
|
||||
|
||||
var geometryGroupCounter = 0;
|
||||
|
||||
return function ( usesFaceMaterial, maxVerticesInGroup ) {
|
||||
|
||||
var f, fl, face, materialIndex,
|
||||
groupHash, hash_map = {},geometryGroup;
|
||||
|
||||
var numMorphTargets = this.morphTargets.length;
|
||||
var numMorphNormals = this.morphNormals.length;
|
||||
|
||||
this.geometryGroups = {};
|
||||
this.geometryGroupsList = [];
|
||||
|
||||
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
|
||||
|
||||
face = this.faces[ f ];
|
||||
materialIndex = usesFaceMaterial ? face.materialIndex : 0;
|
||||
|
||||
if ( ! ( materialIndex in hash_map ) ) {
|
||||
|
||||
hash_map[ materialIndex ] = { 'hash': materialIndex, 'counter': 0 };
|
||||
|
||||
}
|
||||
|
||||
groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
|
||||
|
||||
if ( ! ( groupHash in this.geometryGroups ) ) {
|
||||
|
||||
geometryGroup = { 'id': geometryGroupCounter++, 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
|
||||
this.geometryGroups[ groupHash ] = geometryGroup;
|
||||
this.geometryGroupsList.push(geometryGroup);
|
||||
}
|
||||
|
||||
if ( this.geometryGroups[ groupHash ].vertices + 3 > maxVerticesInGroup ) {
|
||||
|
||||
hash_map[ materialIndex ].counter += 1;
|
||||
groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
|
||||
|
||||
if ( ! ( groupHash in this.geometryGroups ) ) {
|
||||
|
||||
geometryGroup = { 'id': geometryGroupCounter++, 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
|
||||
this.geometryGroups[ groupHash ] = geometryGroup;
|
||||
this.geometryGroupsList.push(geometryGroup);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.geometryGroups[ groupHash ].faces3.push( f );
|
||||
this.geometryGroups[ groupHash ].vertices += 3;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} )(),
|
||||
|
||||
clone: function () {
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
var vertices = this.vertices;
|
||||
|
||||
for ( var i = 0, il = vertices.length; i < il; i ++ ) {
|
||||
|
||||
geometry.vertices.push( vertices[ i ].clone() );
|
||||
|
||||
}
|
||||
|
||||
var faces = this.faces;
|
||||
|
||||
for ( var i = 0, il = faces.length; i < il; i ++ ) {
|
||||
|
||||
geometry.faces.push( faces[ i ].clone() );
|
||||
|
||||
}
|
||||
|
||||
var uvs = this.faceVertexUvs[ 0 ];
|
||||
|
||||
for ( var i = 0, il = uvs.length; i < il; i ++ ) {
|
||||
|
||||
var uv = uvs[ i ], uvCopy = [];
|
||||
|
||||
for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
|
||||
|
||||
uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );
|
||||
|
||||
}
|
||||
|
||||
geometry.faceVertexUvs[ 0 ].push( uvCopy );
|
||||
|
||||
}
|
||||
|
||||
return geometry;
|
||||
|
||||
},
|
||||
|
||||
dispose: function () {
|
||||
|
||||
this.dispatchEvent( { type: 'dispose' } );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.EventDispatcher.prototype.apply( THREE.Geometry.prototype );
|
||||
|
||||
THREE.GeometryIdCount = 0;
|
||||
|
|
@ -1,585 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author mikael emtinger / http://gomo.se/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
*/
|
||||
|
||||
THREE.Object3D = function () {
|
||||
|
||||
this.id = THREE.Object3DIdCount ++;
|
||||
this.uuid = THREE.Math.generateUUID();
|
||||
|
||||
this.name = '';
|
||||
|
||||
this.parent = undefined;
|
||||
this.children = [];
|
||||
|
||||
this.up = THREE.Object3D.DefaultUp.clone();
|
||||
|
||||
var scope = this;
|
||||
|
||||
var position = new THREE.Vector3();
|
||||
var rotation = new THREE.Euler();
|
||||
var quaternion = new THREE.Quaternion();
|
||||
var scale = new THREE.Vector3( 1, 1, 1 );
|
||||
|
||||
rotation.onChange( function () {
|
||||
quaternion.setFromEuler( rotation, false );
|
||||
} );
|
||||
|
||||
quaternion.onChange( function () {
|
||||
rotation.setFromQuaternion( quaternion, undefined, false );
|
||||
} );
|
||||
|
||||
Object.defineProperties( this, {
|
||||
position: {
|
||||
enumerable: true,
|
||||
value: position
|
||||
},
|
||||
rotation: {
|
||||
enumerable: true,
|
||||
value: rotation
|
||||
},
|
||||
quaternion: {
|
||||
enumerable: true,
|
||||
value: quaternion
|
||||
},
|
||||
scale: {
|
||||
enumerable: true,
|
||||
value: scale
|
||||
},
|
||||
} );
|
||||
|
||||
this.renderDepth = null;
|
||||
|
||||
this.rotationAutoUpdate = true;
|
||||
|
||||
this.matrix = new THREE.Matrix4();
|
||||
this.matrixWorld = new THREE.Matrix4();
|
||||
|
||||
this.matrixAutoUpdate = true;
|
||||
this.matrixWorldNeedsUpdate = false;
|
||||
|
||||
this.visible = true;
|
||||
|
||||
this.castShadow = false;
|
||||
this.receiveShadow = false;
|
||||
|
||||
this.frustumCulled = true;
|
||||
|
||||
this.userData = {};
|
||||
|
||||
};
|
||||
|
||||
THREE.Object3D.DefaultUp = new THREE.Vector3( 0, 1, 0 );
|
||||
|
||||
THREE.Object3D.prototype = {
|
||||
|
||||
constructor: THREE.Object3D,
|
||||
|
||||
get eulerOrder () {
|
||||
|
||||
console.warn( 'THREE.Object3D: .eulerOrder has been moved to .rotation.order.' );
|
||||
|
||||
return this.rotation.order;
|
||||
|
||||
},
|
||||
|
||||
set eulerOrder ( value ) {
|
||||
|
||||
console.warn( 'THREE.Object3D: .eulerOrder has been moved to .rotation.order.' );
|
||||
|
||||
this.rotation.order = value;
|
||||
|
||||
},
|
||||
|
||||
get useQuaternion () {
|
||||
|
||||
console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
|
||||
|
||||
},
|
||||
|
||||
set useQuaternion ( value ) {
|
||||
|
||||
console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
|
||||
|
||||
},
|
||||
|
||||
applyMatrix: function ( matrix ) {
|
||||
|
||||
this.matrix.multiplyMatrices( matrix, this.matrix );
|
||||
|
||||
this.matrix.decompose( this.position, this.quaternion, this.scale );
|
||||
|
||||
},
|
||||
|
||||
setRotationFromAxisAngle: function ( axis, angle ) {
|
||||
|
||||
// assumes axis is normalized
|
||||
|
||||
this.quaternion.setFromAxisAngle( axis, angle );
|
||||
|
||||
},
|
||||
|
||||
setRotationFromEuler: function ( euler ) {
|
||||
|
||||
this.quaternion.setFromEuler( euler, true );
|
||||
|
||||
},
|
||||
|
||||
setRotationFromMatrix: function ( m ) {
|
||||
|
||||
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
|
||||
|
||||
this.quaternion.setFromRotationMatrix( m );
|
||||
|
||||
},
|
||||
|
||||
setRotationFromQuaternion: function ( q ) {
|
||||
|
||||
// assumes q is normalized
|
||||
|
||||
this.quaternion.copy( q );
|
||||
|
||||
},
|
||||
|
||||
rotateOnAxis: function () {
|
||||
|
||||
// rotate object on axis in object space
|
||||
// axis is assumed to be normalized
|
||||
|
||||
var q1 = new THREE.Quaternion();
|
||||
|
||||
return function ( axis, angle ) {
|
||||
|
||||
q1.setFromAxisAngle( axis, angle );
|
||||
|
||||
this.quaternion.multiply( q1 );
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}(),
|
||||
|
||||
rotateX: function () {
|
||||
|
||||
var v1 = new THREE.Vector3( 1, 0, 0 );
|
||||
|
||||
return function ( angle ) {
|
||||
|
||||
return this.rotateOnAxis( v1, angle );
|
||||
|
||||
};
|
||||
|
||||
}(),
|
||||
|
||||
rotateY: function () {
|
||||
|
||||
var v1 = new THREE.Vector3( 0, 1, 0 );
|
||||
|
||||
return function ( angle ) {
|
||||
|
||||
return this.rotateOnAxis( v1, angle );
|
||||
|
||||
};
|
||||
|
||||
}(),
|
||||
|
||||
rotateZ: function () {
|
||||
|
||||
var v1 = new THREE.Vector3( 0, 0, 1 );
|
||||
|
||||
return function ( angle ) {
|
||||
|
||||
return this.rotateOnAxis( v1, angle );
|
||||
|
||||
};
|
||||
|
||||
}(),
|
||||
|
||||
translateOnAxis: function () {
|
||||
|
||||
// translate object by distance along axis in object space
|
||||
// axis is assumed to be normalized
|
||||
|
||||
var v1 = new THREE.Vector3();
|
||||
|
||||
return function ( axis, distance ) {
|
||||
|
||||
v1.copy( axis ).applyQuaternion( this.quaternion );
|
||||
|
||||
this.position.add( v1.multiplyScalar( distance ) );
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}(),
|
||||
|
||||
translate: function ( distance, axis ) {
|
||||
|
||||
console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
|
||||
return this.translateOnAxis( axis, distance );
|
||||
|
||||
},
|
||||
|
||||
translateX: function () {
|
||||
|
||||
var v1 = new THREE.Vector3( 1, 0, 0 );
|
||||
|
||||
return function ( distance ) {
|
||||
|
||||
return this.translateOnAxis( v1, distance );
|
||||
|
||||
};
|
||||
|
||||
}(),
|
||||
|
||||
translateY: function () {
|
||||
|
||||
var v1 = new THREE.Vector3( 0, 1, 0 );
|
||||
|
||||
return function ( distance ) {
|
||||
|
||||
return this.translateOnAxis( v1, distance );
|
||||
|
||||
};
|
||||
|
||||
}(),
|
||||
|
||||
translateZ: function () {
|
||||
|
||||
var v1 = new THREE.Vector3( 0, 0, 1 );
|
||||
|
||||
return function ( distance ) {
|
||||
|
||||
return this.translateOnAxis( v1, distance );
|
||||
|
||||
};
|
||||
|
||||
}(),
|
||||
|
||||
localToWorld: function ( vector ) {
|
||||
|
||||
return vector.applyMatrix4( this.matrixWorld );
|
||||
|
||||
},
|
||||
|
||||
worldToLocal: function () {
|
||||
|
||||
var m1 = new THREE.Matrix4();
|
||||
|
||||
return function ( vector ) {
|
||||
|
||||
return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) );
|
||||
|
||||
};
|
||||
|
||||
}(),
|
||||
|
||||
lookAt: function () {
|
||||
|
||||
// This routine does not support objects with rotated and/or translated parent(s)
|
||||
|
||||
var m1 = new THREE.Matrix4();
|
||||
|
||||
return function ( vector ) {
|
||||
|
||||
m1.lookAt( vector, this.position, this.up );
|
||||
|
||||
this.quaternion.setFromRotationMatrix( m1 );
|
||||
|
||||
};
|
||||
|
||||
}(),
|
||||
|
||||
add: function ( object ) {
|
||||
|
||||
if ( arguments.length > 1 ) {
|
||||
|
||||
for ( var i = 0; i < arguments.length; i++ ) {
|
||||
|
||||
this.add( arguments[ i ] );
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
};
|
||||
|
||||
if ( object === this ) {
|
||||
|
||||
console.error( "THREE.Object3D.add:", object, "can't be added as a child of itself." );
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
if ( object instanceof THREE.Object3D ) {
|
||||
|
||||
if ( object.parent !== undefined ) {
|
||||
|
||||
object.parent.remove( object );
|
||||
|
||||
}
|
||||
|
||||
object.parent = this;
|
||||
object.dispatchEvent( { type: 'added' } );
|
||||
|
||||
this.children.push( object );
|
||||
|
||||
// add to scene
|
||||
|
||||
var scene = this;
|
||||
|
||||
while ( scene.parent !== undefined ) {
|
||||
|
||||
scene = scene.parent;
|
||||
|
||||
}
|
||||
|
||||
if ( scene !== undefined && scene instanceof THREE.Scene ) {
|
||||
|
||||
scene.__addObject( object );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
console.error( "THREE.Object3D.add:", object, "is not an instance of THREE.Object3D." );
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
remove: function ( object ) {
|
||||
|
||||
if ( arguments.length > 1 ) {
|
||||
|
||||
for ( var i = 0; i < arguments.length; i++ ) {
|
||||
|
||||
this.remove( arguments[ i ] );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var index = this.children.indexOf( object );
|
||||
|
||||
if ( index !== - 1 ) {
|
||||
|
||||
object.parent = undefined;
|
||||
object.dispatchEvent( { type: 'removed' } );
|
||||
|
||||
this.children.splice( index, 1 );
|
||||
|
||||
// remove from scene
|
||||
|
||||
var scene = this;
|
||||
|
||||
while ( scene.parent !== undefined ) {
|
||||
|
||||
scene = scene.parent;
|
||||
|
||||
}
|
||||
|
||||
if ( scene !== undefined && scene instanceof THREE.Scene ) {
|
||||
|
||||
scene.__removeObject( object );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
raycast: function () {},
|
||||
|
||||
traverse: function ( callback ) {
|
||||
|
||||
callback( this );
|
||||
|
||||
for ( var i = 0, l = this.children.length; i < l; i ++ ) {
|
||||
|
||||
this.children[ i ].traverse( callback );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
traverseVisible: function ( callback ) {
|
||||
|
||||
if ( this.visible === false ) return;
|
||||
|
||||
callback( this );
|
||||
|
||||
for ( var i = 0, l = this.children.length; i < l; i ++ ) {
|
||||
|
||||
this.children[ i ].traverseVisible( callback );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
getObjectById: function ( id, recursive ) {
|
||||
|
||||
for ( var i = 0, l = this.children.length; i < l; i ++ ) {
|
||||
|
||||
var child = this.children[ i ];
|
||||
|
||||
if ( child.id === id ) {
|
||||
|
||||
return child;
|
||||
|
||||
}
|
||||
|
||||
if ( recursive === true ) {
|
||||
|
||||
child = child.getObjectById( id, recursive );
|
||||
|
||||
if ( child !== undefined ) {
|
||||
|
||||
return child;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
},
|
||||
|
||||
getObjectByName: function ( name, recursive ) {
|
||||
|
||||
for ( var i = 0, l = this.children.length; i < l; i ++ ) {
|
||||
|
||||
var child = this.children[ i ];
|
||||
|
||||
if ( child.name === name ) {
|
||||
|
||||
return child;
|
||||
|
||||
}
|
||||
|
||||
if ( recursive === true ) {
|
||||
|
||||
child = child.getObjectByName( name, recursive );
|
||||
|
||||
if ( child !== undefined ) {
|
||||
|
||||
return child;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
},
|
||||
|
||||
getChildByName: function ( name, recursive ) {
|
||||
|
||||
console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
|
||||
return this.getObjectByName( name, recursive );
|
||||
|
||||
},
|
||||
|
||||
updateMatrix: function () {
|
||||
|
||||
this.matrix.compose( this.position, this.quaternion, this.scale );
|
||||
|
||||
this.matrixWorldNeedsUpdate = true;
|
||||
|
||||
},
|
||||
|
||||
updateMatrixWorld: function ( force ) {
|
||||
|
||||
if ( this.matrixAutoUpdate === true ) this.updateMatrix();
|
||||
|
||||
if ( this.matrixWorldNeedsUpdate === true || force === true ) {
|
||||
|
||||
if ( this.parent === undefined ) {
|
||||
|
||||
this.matrixWorld.copy( this.matrix );
|
||||
|
||||
} else {
|
||||
|
||||
this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
|
||||
|
||||
}
|
||||
|
||||
this.matrixWorldNeedsUpdate = false;
|
||||
|
||||
force = true;
|
||||
|
||||
}
|
||||
|
||||
// update children
|
||||
|
||||
for ( var i = 0, l = this.children.length; i < l; i ++ ) {
|
||||
|
||||
this.children[ i ].updateMatrixWorld( force );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
clone: function ( object, recursive ) {
|
||||
|
||||
if ( object === undefined ) object = new THREE.Object3D();
|
||||
if ( recursive === undefined ) recursive = true;
|
||||
|
||||
object.name = this.name;
|
||||
|
||||
object.up.copy( this.up );
|
||||
|
||||
object.position.copy( this.position );
|
||||
object.quaternion.copy( this.quaternion );
|
||||
object.scale.copy( this.scale );
|
||||
|
||||
object.renderDepth = this.renderDepth;
|
||||
|
||||
object.rotationAutoUpdate = this.rotationAutoUpdate;
|
||||
|
||||
object.matrix.copy( this.matrix );
|
||||
object.matrixWorld.copy( this.matrixWorld );
|
||||
|
||||
object.matrixAutoUpdate = this.matrixAutoUpdate;
|
||||
object.matrixWorldNeedsUpdate = this.matrixWorldNeedsUpdate;
|
||||
|
||||
object.visible = this.visible;
|
||||
|
||||
object.castShadow = this.castShadow;
|
||||
object.receiveShadow = this.receiveShadow;
|
||||
|
||||
object.frustumCulled = this.frustumCulled;
|
||||
|
||||
object.userData = JSON.parse( JSON.stringify( this.userData ) );
|
||||
|
||||
if ( recursive === true ) {
|
||||
|
||||
for ( var i = 0; i < this.children.length; i ++ ) {
|
||||
|
||||
var child = this.children[ i ];
|
||||
object.add( child.clone() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return object;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.EventDispatcher.prototype.apply( THREE.Object3D.prototype );
|
||||
|
||||
THREE.Object3DIdCount = 0;
|
||||
|
|
@ -1,857 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author supereggbert / http://www.paulbrunt.co.uk/
|
||||
* @author julianwa / https://github.com/julianwa
|
||||
*/
|
||||
|
||||
THREE.Projector = function () {
|
||||
|
||||
var _object, _objectCount, _objectPool = [], _objectPoolLength = 0,
|
||||
_vertex, _vertexCount, _vertexPool = [], _vertexPoolLength = 0,
|
||||
_face, _faceCount, _facePool = [], _facePoolLength = 0,
|
||||
_line, _lineCount, _linePool = [], _linePoolLength = 0,
|
||||
_sprite, _spriteCount, _spritePool = [], _spritePoolLength = 0,
|
||||
|
||||
_renderData = { objects: [], lights: [], elements: [] },
|
||||
|
||||
_vA = new THREE.Vector3(),
|
||||
_vB = new THREE.Vector3(),
|
||||
_vC = new THREE.Vector3(),
|
||||
|
||||
_vector3 = new THREE.Vector3(),
|
||||
_vector4 = new THREE.Vector4(),
|
||||
|
||||
_clipBox = new THREE.Box3( new THREE.Vector3( - 1, - 1, - 1 ), new THREE.Vector3( 1, 1, 1 ) ),
|
||||
_boundingBox = new THREE.Box3(),
|
||||
_points3 = new Array( 3 ),
|
||||
_points4 = new Array( 4 ),
|
||||
|
||||
_viewMatrix = new THREE.Matrix4(),
|
||||
_viewProjectionMatrix = new THREE.Matrix4(),
|
||||
|
||||
_modelMatrix,
|
||||
_modelViewProjectionMatrix = new THREE.Matrix4(),
|
||||
|
||||
_normalMatrix = new THREE.Matrix3(),
|
||||
|
||||
_frustum = new THREE.Frustum(),
|
||||
|
||||
_clippedVertex1PositionScreen = new THREE.Vector4(),
|
||||
_clippedVertex2PositionScreen = new THREE.Vector4();
|
||||
|
||||
this.projectVector = function ( vector, camera ) {
|
||||
|
||||
camera.matrixWorldInverse.getInverse( camera.matrixWorld );
|
||||
|
||||
_viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
|
||||
|
||||
return vector.applyProjection( _viewProjectionMatrix );
|
||||
|
||||
};
|
||||
|
||||
this.unprojectVector = function () {
|
||||
|
||||
var projectionMatrixInverse = new THREE.Matrix4();
|
||||
|
||||
return function ( vector, camera ) {
|
||||
|
||||
projectionMatrixInverse.getInverse( camera.projectionMatrix );
|
||||
_viewProjectionMatrix.multiplyMatrices( camera.matrixWorld, projectionMatrixInverse );
|
||||
|
||||
return vector.applyProjection( _viewProjectionMatrix );
|
||||
|
||||
};
|
||||
|
||||
}();
|
||||
|
||||
this.pickingRay = function ( vector, camera ) {
|
||||
|
||||
// set two vectors with opposing z values
|
||||
vector.z = - 1.0;
|
||||
var end = new THREE.Vector3( vector.x, vector.y, 1.0 );
|
||||
|
||||
this.unprojectVector( vector, camera );
|
||||
this.unprojectVector( end, camera );
|
||||
|
||||
// find direction from vector to end
|
||||
end.sub( vector ).normalize();
|
||||
|
||||
return new THREE.Raycaster( vector, end );
|
||||
|
||||
};
|
||||
|
||||
var RenderList = function () {
|
||||
|
||||
var normals = [];
|
||||
var uvs = [];
|
||||
|
||||
var object = null;
|
||||
var material = null;
|
||||
|
||||
var normalMatrix = new THREE.Matrix3();
|
||||
|
||||
var setObject = function ( value ) {
|
||||
|
||||
object = value;
|
||||
material = object.material;
|
||||
|
||||
normalMatrix.getNormalMatrix( object.matrixWorld );
|
||||
|
||||
normals.length = 0;
|
||||
uvs.length = 0;
|
||||
|
||||
};
|
||||
|
||||
var projectVertex = function ( vertex ) {
|
||||
|
||||
var position = vertex.position;
|
||||
var positionWorld = vertex.positionWorld;
|
||||
var positionScreen = vertex.positionScreen;
|
||||
|
||||
positionWorld.copy( position ).applyMatrix4( _modelMatrix );
|
||||
positionScreen.copy( positionWorld ).applyMatrix4( _viewProjectionMatrix );
|
||||
|
||||
var invW = 1 / positionScreen.w;
|
||||
|
||||
positionScreen.x *= invW;
|
||||
positionScreen.y *= invW;
|
||||
positionScreen.z *= invW;
|
||||
|
||||
vertex.visible = positionScreen.x >= - 1 && positionScreen.x <= 1 &&
|
||||
positionScreen.y >= - 1 && positionScreen.y <= 1 &&
|
||||
positionScreen.z >= - 1 && positionScreen.z <= 1;
|
||||
|
||||
};
|
||||
|
||||
var pushVertex = function ( x, y, z ) {
|
||||
|
||||
_vertex = getNextVertexInPool();
|
||||
_vertex.position.set( x, y, z );
|
||||
|
||||
projectVertex( _vertex );
|
||||
|
||||
};
|
||||
|
||||
var pushNormal = function ( x, y, z ) {
|
||||
|
||||
normals.push( x, y, z );
|
||||
|
||||
};
|
||||
|
||||
var pushUv = function ( x, y ) {
|
||||
|
||||
uvs.push( x, y );
|
||||
|
||||
};
|
||||
|
||||
var checkTriangleVisibility = function ( v1, v2, v3 ) {
|
||||
|
||||
if ( v1.visible === true || v2.visible === true || v3.visible === true ) return true;
|
||||
|
||||
_points3[ 0 ] = v1.positionScreen;
|
||||
_points3[ 1 ] = v2.positionScreen;
|
||||
_points3[ 2 ] = v3.positionScreen;
|
||||
|
||||
return _clipBox.isIntersectionBox( _boundingBox.setFromPoints( _points3 ) );
|
||||
|
||||
};
|
||||
|
||||
var checkBackfaceCulling = function ( v1, v2, v3 ) {
|
||||
|
||||
return ( ( 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;
|
||||
|
||||
};
|
||||
|
||||
var pushLine = function ( a, b ) {
|
||||
|
||||
var v1 = _vertexPool[ a ];
|
||||
var v2 = _vertexPool[ b ];
|
||||
|
||||
_line = getNextLineInPool();
|
||||
|
||||
_line.id = object.id;
|
||||
_line.v1.copy( v1 );
|
||||
_line.v2.copy( v2 );
|
||||
_line.z = ( v1.positionScreen.z + v2.positionScreen.z ) / 2;
|
||||
|
||||
_line.material = object.material;
|
||||
|
||||
_renderData.elements.push( _line );
|
||||
|
||||
};
|
||||
|
||||
var pushTriangle = function ( a, b, c ) {
|
||||
|
||||
var v1 = _vertexPool[ a ];
|
||||
var v2 = _vertexPool[ b ];
|
||||
var v3 = _vertexPool[ c ];
|
||||
|
||||
if ( checkTriangleVisibility( v1, v2, v3 ) === false ) return;
|
||||
|
||||
if ( material.side === THREE.DoubleSide || checkBackfaceCulling( v1, v2, v3 ) === true ) {
|
||||
|
||||
_face = getNextFaceInPool();
|
||||
|
||||
_face.id = object.id;
|
||||
_face.v1.copy( v1 );
|
||||
_face.v2.copy( v2 );
|
||||
_face.v3.copy( v3 );
|
||||
_face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
|
||||
|
||||
for ( var i = 0; i < 3; i ++ ) {
|
||||
|
||||
var offset = arguments[ i ] * 3;
|
||||
var normal = _face.vertexNormalsModel[ i ];
|
||||
|
||||
normal.set( normals[ offset ], normals[ offset + 1 ], normals[ offset + 2 ] );
|
||||
normal.applyMatrix3( normalMatrix ).normalize();
|
||||
|
||||
var offset2 = arguments[ i ] * 2;
|
||||
|
||||
var uv = _face.uvs[ i ];
|
||||
uv.set( uvs[ offset2 ], uvs[ offset2 + 1 ] );
|
||||
|
||||
}
|
||||
|
||||
_face.vertexNormalsLength = 3;
|
||||
|
||||
_face.material = object.material;
|
||||
|
||||
_renderData.elements.push( _face );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return {
|
||||
setObject: setObject,
|
||||
projectVertex: projectVertex,
|
||||
checkTriangleVisibility: checkTriangleVisibility,
|
||||
checkBackfaceCulling: checkBackfaceCulling,
|
||||
pushVertex: pushVertex,
|
||||
pushNormal: pushNormal,
|
||||
pushUv: pushUv,
|
||||
pushLine: pushLine,
|
||||
pushTriangle: pushTriangle
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var renderList = new RenderList();
|
||||
|
||||
this.projectScene = function ( scene, camera, sortObjects, sortElements ) {
|
||||
|
||||
_faceCount = 0;
|
||||
_lineCount = 0;
|
||||
_spriteCount = 0;
|
||||
|
||||
_renderData.elements.length = 0;
|
||||
|
||||
if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
|
||||
if ( camera.parent === undefined ) camera.updateMatrixWorld();
|
||||
|
||||
_viewMatrix.copy( camera.matrixWorldInverse.getInverse( camera.matrixWorld ) );
|
||||
_viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix );
|
||||
|
||||
_frustum.setFromMatrix( _viewProjectionMatrix );
|
||||
|
||||
//
|
||||
|
||||
_objectCount = 0;
|
||||
|
||||
_renderData.objects.length = 0;
|
||||
_renderData.lights.length = 0;
|
||||
|
||||
scene.traverseVisible( function ( object ) {
|
||||
|
||||
if ( object instanceof THREE.Light ) {
|
||||
|
||||
_renderData.lights.push( object );
|
||||
|
||||
} else if ( object instanceof THREE.Mesh || object instanceof THREE.Segment || object instanceof THREE.Sprite ) {
|
||||
|
||||
if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
|
||||
|
||||
_object = getNextObjectInPool();
|
||||
_object.id = object.id;
|
||||
_object.object = object;
|
||||
|
||||
if ( object.renderDepth !== null ) {
|
||||
|
||||
_object.z = object.renderDepth;
|
||||
|
||||
} else {
|
||||
|
||||
_vector3.setFromMatrixPosition( object.matrixWorld );
|
||||
_vector3.applyProjection( _viewProjectionMatrix );
|
||||
_object.z = _vector3.z;
|
||||
|
||||
}
|
||||
|
||||
_renderData.objects.push( _object );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
if ( sortObjects === true ) {
|
||||
|
||||
_renderData.objects.sort( painterSort );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
for ( var o = 0, ol = _renderData.objects.length; o < ol; o ++ ) {
|
||||
|
||||
var object = _renderData.objects[ o ].object;
|
||||
var geometry = object.geometry;
|
||||
|
||||
renderList.setObject( object );
|
||||
|
||||
_modelMatrix = object.matrixWorld;
|
||||
|
||||
_vertexCount = 0;
|
||||
|
||||
if ( object instanceof THREE.Mesh ) {
|
||||
|
||||
if ( geometry instanceof THREE.BufferGeometry ) {
|
||||
|
||||
var attributes = geometry.attributes;
|
||||
var offsets = geometry.offsets;
|
||||
|
||||
if ( attributes.position === undefined ) continue;
|
||||
|
||||
var positions = attributes.position.array;
|
||||
|
||||
for ( var i = 0, l = positions.length; i < l; i += 3 ) {
|
||||
|
||||
renderList.pushVertex( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
|
||||
|
||||
}
|
||||
|
||||
if ( attributes.normal !== undefined ) {
|
||||
|
||||
var normals = attributes.normal.array;
|
||||
|
||||
for ( var i = 0, l = normals.length; i < l; i += 3 ) {
|
||||
|
||||
renderList.pushNormal( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( attributes.uv !== undefined ) {
|
||||
|
||||
var uvs = attributes.uv.array;
|
||||
|
||||
for ( var i = 0, l = uvs.length; i < l; i += 2 ) {
|
||||
|
||||
renderList.pushUv( uvs[ i ], uvs[ i + 1 ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( attributes.index !== undefined ) {
|
||||
|
||||
var indices = attributes.index.array;
|
||||
|
||||
if ( offsets.length > 0 ) {
|
||||
|
||||
for ( var o = 0; o < offsets.length; o ++ ) {
|
||||
|
||||
var offset = offsets[ o ];
|
||||
var index = offset.index;
|
||||
|
||||
for ( var i = offset.start, l = offset.start + offset.count; i < l; i += 3 ) {
|
||||
|
||||
renderList.pushTriangle( indices[ i ] + index, indices[ i + 1 ] + index, indices[ i + 2 ] + index );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for ( var i = 0, l = indices.length; i < l; i += 3 ) {
|
||||
|
||||
renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for ( var i = 0, l = positions.length / 3; i < l; i += 3 ) {
|
||||
|
||||
renderList.pushTriangle( i, i + 1, i + 2 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( geometry instanceof THREE.Geometry ) {
|
||||
|
||||
var vertices = geometry.vertices;
|
||||
var faces = geometry.faces;
|
||||
var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
|
||||
|
||||
_normalMatrix.getNormalMatrix( _modelMatrix );
|
||||
|
||||
var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
|
||||
var objectMaterials = isFaceMaterial === true ? object.material : null;
|
||||
|
||||
for ( var v = 0, vl = vertices.length; v < vl; v ++ ) {
|
||||
|
||||
var vertex = vertices[ v ];
|
||||
renderList.pushVertex( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
}
|
||||
|
||||
for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
|
||||
|
||||
var face = faces[ f ];
|
||||
|
||||
var material = isFaceMaterial === true
|
||||
? objectMaterials.materials[ face.materialIndex ]
|
||||
: object.material;
|
||||
|
||||
if ( material === undefined ) continue;
|
||||
|
||||
var side = material.side;
|
||||
|
||||
var v1 = _vertexPool[ face.a ];
|
||||
var v2 = _vertexPool[ face.b ];
|
||||
var v3 = _vertexPool[ face.c ];
|
||||
|
||||
if ( material.morphTargets === true ) {
|
||||
|
||||
var morphTargets = geometry.morphTargets;
|
||||
var morphInfluences = object.morphTargetInfluences;
|
||||
|
||||
var v1p = v1.position;
|
||||
var v2p = v2.position;
|
||||
var v3p = v3.position;
|
||||
|
||||
_vA.set( 0, 0, 0 );
|
||||
_vB.set( 0, 0, 0 );
|
||||
_vC.set( 0, 0, 0 );
|
||||
|
||||
for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
|
||||
|
||||
var influence = morphInfluences[ t ];
|
||||
|
||||
if ( influence === 0 ) continue;
|
||||
|
||||
var targets = morphTargets[ t ].vertices;
|
||||
|
||||
_vA.x += ( targets[ face.a ].x - v1p.x ) * influence;
|
||||
_vA.y += ( targets[ face.a ].y - v1p.y ) * influence;
|
||||
_vA.z += ( targets[ face.a ].z - v1p.z ) * influence;
|
||||
|
||||
_vB.x += ( targets[ face.b ].x - v2p.x ) * influence;
|
||||
_vB.y += ( targets[ face.b ].y - v2p.y ) * influence;
|
||||
_vB.z += ( targets[ face.b ].z - v2p.z ) * influence;
|
||||
|
||||
_vC.x += ( targets[ face.c ].x - v3p.x ) * influence;
|
||||
_vC.y += ( targets[ face.c ].y - v3p.y ) * influence;
|
||||
_vC.z += ( targets[ face.c ].z - v3p.z ) * influence;
|
||||
|
||||
}
|
||||
|
||||
v1.position.add( _vA );
|
||||
v2.position.add( _vB );
|
||||
v3.position.add( _vC );
|
||||
|
||||
renderList.projectVertex( v1 );
|
||||
renderList.projectVertex( v2 );
|
||||
renderList.projectVertex( v3 );
|
||||
|
||||
}
|
||||
|
||||
if ( renderList.checkTriangleVisibility( v1, v2, v3 ) === false ) continue;
|
||||
|
||||
var visible = renderList.checkBackfaceCulling( v1, v2, v3 );
|
||||
|
||||
if ( side !== THREE.DoubleSide ) {
|
||||
if ( side === THREE.FrontSide && visible === false ) continue;
|
||||
if ( side === THREE.BackSide && visible === true ) continue;
|
||||
}
|
||||
|
||||
_face = getNextFaceInPool();
|
||||
|
||||
_face.id = object.id;
|
||||
_face.v1.copy( v1 );
|
||||
_face.v2.copy( v2 );
|
||||
_face.v3.copy( v3 );
|
||||
|
||||
_face.normalModel.copy( face.normal );
|
||||
|
||||
if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
|
||||
|
||||
_face.normalModel.negate();
|
||||
|
||||
}
|
||||
|
||||
_face.normalModel.applyMatrix3( _normalMatrix ).normalize();
|
||||
|
||||
var faceVertexNormals = face.vertexNormals;
|
||||
|
||||
for ( var n = 0, nl = Math.min( faceVertexNormals.length, 3 ); n < nl; n ++ ) {
|
||||
|
||||
var normalModel = _face.vertexNormalsModel[ n ];
|
||||
normalModel.copy( faceVertexNormals[ n ] );
|
||||
|
||||
if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
|
||||
|
||||
normalModel.negate();
|
||||
|
||||
}
|
||||
|
||||
normalModel.applyMatrix3( _normalMatrix ).normalize();
|
||||
|
||||
}
|
||||
|
||||
_face.vertexNormalsLength = faceVertexNormals.length;
|
||||
|
||||
var vertexUvs = faceVertexUvs[ f ];
|
||||
|
||||
if ( vertexUvs !== undefined ) {
|
||||
|
||||
for ( var u = 0; u < 3; u ++ ) {
|
||||
|
||||
_face.uvs[ u ].copy( vertexUvs[ u ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_face.color = face.color;
|
||||
_face.material = material;
|
||||
|
||||
_face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
|
||||
|
||||
_renderData.elements.push( _face );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( object instanceof THREE.Segment ) {
|
||||
|
||||
if ( geometry instanceof THREE.BufferGeometry ) {
|
||||
|
||||
var attributes = geometry.attributes;
|
||||
|
||||
if ( attributes.position !== undefined ) {
|
||||
|
||||
var positions = attributes.position.array;
|
||||
|
||||
for ( var i = 0, l = positions.length; i < l; i += 3 ) {
|
||||
|
||||
renderList.pushVertex( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
|
||||
|
||||
}
|
||||
|
||||
if ( attributes.index !== undefined ) {
|
||||
|
||||
var indices = attributes.index.array;
|
||||
|
||||
for ( var i = 0, l = indices.length; i < l; i += 2 ) {
|
||||
|
||||
renderList.pushLine( indices[ i ], indices[ i + 1 ] );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
var step = object.type === THREE.LinePieces ? 2 : 1;
|
||||
|
||||
for ( var i = 0, l = ( positions.length / 3 ) - 1; i < l; i += step ) {
|
||||
|
||||
renderList.pushLine( i, i + 1 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( geometry instanceof THREE.Geometry ) {
|
||||
|
||||
_modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix );
|
||||
|
||||
var vertices = object.geometry.vertices;
|
||||
|
||||
if ( vertices.length === 0 ) continue;
|
||||
|
||||
v1 = getNextVertexInPool();
|
||||
v1.positionScreen.copy( vertices[ 0 ] ).applyMatrix4( _modelViewProjectionMatrix );
|
||||
|
||||
// Handle LineStrip and LinePieces
|
||||
var step = object.type === THREE.LinePieces ? 2 : 1;
|
||||
|
||||
for ( var v = 1, vl = vertices.length; v < vl; v ++ ) {
|
||||
|
||||
v1 = getNextVertexInPool();
|
||||
v1.positionScreen.copy( vertices[ v ] ).applyMatrix4( _modelViewProjectionMatrix );
|
||||
|
||||
if ( ( v + 1 ) % step > 0 ) continue;
|
||||
|
||||
v2 = _vertexPool[ _vertexCount - 2 ];
|
||||
|
||||
_clippedVertex1PositionScreen.copy( v1.positionScreen );
|
||||
_clippedVertex2PositionScreen.copy( v2.positionScreen );
|
||||
|
||||
if ( clipLine( _clippedVertex1PositionScreen, _clippedVertex2PositionScreen ) === true ) {
|
||||
|
||||
// Perform the perspective divide
|
||||
_clippedVertex1PositionScreen.multiplyScalar( 1 / _clippedVertex1PositionScreen.w );
|
||||
_clippedVertex2PositionScreen.multiplyScalar( 1 / _clippedVertex2PositionScreen.w );
|
||||
|
||||
_line = getNextLineInPool();
|
||||
|
||||
_line.id = object.id;
|
||||
_line.v1.positionScreen.copy( _clippedVertex1PositionScreen );
|
||||
_line.v2.positionScreen.copy( _clippedVertex2PositionScreen );
|
||||
|
||||
_line.z = Math.max( _clippedVertex1PositionScreen.z, _clippedVertex2PositionScreen.z );
|
||||
|
||||
_line.material = object.material;
|
||||
|
||||
if ( object.material.vertexColors === THREE.VertexColors ) {
|
||||
|
||||
_line.vertexColors[ 0 ].copy( object.geometry.colors[ v ] );
|
||||
_line.vertexColors[ 1 ].copy( object.geometry.colors[ v - 1 ] );
|
||||
|
||||
}
|
||||
|
||||
_renderData.elements.push( _line );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( object instanceof THREE.Sprite ) {
|
||||
|
||||
_vector4.set( _modelMatrix.elements[ 12 ], _modelMatrix.elements[ 13 ], _modelMatrix.elements[ 14 ], 1 );
|
||||
_vector4.applyMatrix4( _viewProjectionMatrix );
|
||||
|
||||
var invW = 1 / _vector4.w;
|
||||
|
||||
_vector4.z *= invW;
|
||||
|
||||
if ( _vector4.z >= - 1 && _vector4.z <= 1 ) {
|
||||
|
||||
_sprite = getNextSpriteInPool();
|
||||
_sprite.id = object.id;
|
||||
_sprite.x = _vector4.x * invW;
|
||||
_sprite.y = _vector4.y * invW;
|
||||
_sprite.z = _vector4.z;
|
||||
_sprite.object = object;
|
||||
|
||||
_sprite.rotation = object.rotation;
|
||||
|
||||
_sprite.scale.x = object.scale.x * Math.abs( _sprite.x - ( _vector4.x + camera.projectionMatrix.elements[ 0 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 12 ] ) );
|
||||
_sprite.scale.y = object.scale.y * Math.abs( _sprite.y - ( _vector4.y + camera.projectionMatrix.elements[ 5 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 13 ] ) );
|
||||
|
||||
_sprite.material = object.material;
|
||||
|
||||
_renderData.elements.push( _sprite );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( sortElements === true ) _renderData.elements.sort( painterSort );
|
||||
|
||||
return _renderData;
|
||||
|
||||
};
|
||||
|
||||
// Pools
|
||||
|
||||
function getNextObjectInPool() {
|
||||
|
||||
if ( _objectCount === _objectPoolLength ) {
|
||||
|
||||
var object = new THREE.RenderableObject();
|
||||
_objectPool.push( object );
|
||||
_objectPoolLength ++;
|
||||
_objectCount ++;
|
||||
return object;
|
||||
|
||||
}
|
||||
|
||||
return _objectPool[ _objectCount ++ ];
|
||||
|
||||
}
|
||||
|
||||
function getNextVertexInPool() {
|
||||
|
||||
if ( _vertexCount === _vertexPoolLength ) {
|
||||
|
||||
var vertex = new THREE.RenderableVertex();
|
||||
_vertexPool.push( vertex );
|
||||
_vertexPoolLength ++;
|
||||
_vertexCount ++;
|
||||
return vertex;
|
||||
|
||||
}
|
||||
|
||||
return _vertexPool[ _vertexCount ++ ];
|
||||
|
||||
}
|
||||
|
||||
function getNextFaceInPool() {
|
||||
|
||||
if ( _faceCount === _facePoolLength ) {
|
||||
|
||||
var face = new THREE.RenderableFace();
|
||||
_facePool.push( face );
|
||||
_facePoolLength ++;
|
||||
_faceCount ++;
|
||||
return face;
|
||||
|
||||
}
|
||||
|
||||
return _facePool[ _faceCount ++ ];
|
||||
|
||||
|
||||
}
|
||||
|
||||
function getNextLineInPool() {
|
||||
|
||||
if ( _lineCount === _linePoolLength ) {
|
||||
|
||||
var line = new THREE.RenderableLine();
|
||||
_linePool.push( line );
|
||||
_linePoolLength ++;
|
||||
_lineCount ++
|
||||
return line;
|
||||
|
||||
}
|
||||
|
||||
return _linePool[ _lineCount ++ ];
|
||||
|
||||
}
|
||||
|
||||
function getNextSpriteInPool() {
|
||||
|
||||
if ( _spriteCount === _spritePoolLength ) {
|
||||
|
||||
var sprite = new THREE.RenderableSprite();
|
||||
_spritePool.push( sprite );
|
||||
_spritePoolLength ++;
|
||||
_spriteCount ++
|
||||
return sprite;
|
||||
|
||||
}
|
||||
|
||||
return _spritePool[ _spriteCount ++ ];
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
function painterSort( a, b ) {
|
||||
|
||||
if ( a.z !== b.z ) {
|
||||
|
||||
return b.z - a.z;
|
||||
|
||||
} else if ( a.id !== b.id ) {
|
||||
|
||||
return a.id - b.id;
|
||||
|
||||
} else {
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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.lerp( s2, alpha1 );
|
||||
s2.lerp( s1, 1 - alpha2 );
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author bhouston / http://exocortex.com/
|
||||
* @author stephomi / http://stephaneginier.com/
|
||||
*/
|
||||
|
||||
( function ( THREE ) {
|
||||
|
||||
THREE.Raycaster = function ( origin, direction, near, far ) {
|
||||
|
||||
this.ray = new THREE.Ray( origin, direction );
|
||||
// direction is assumed to be normalized (for accurate distance calculations)
|
||||
|
||||
this.near = near || 0;
|
||||
this.far = far || Infinity;
|
||||
|
||||
this.params = {
|
||||
Sprite: {},
|
||||
Mesh: {},
|
||||
PointCloud: { threshold: 1 },
|
||||
LOD: {},
|
||||
Segment: {}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
var descSort = function ( a, b ) {
|
||||
|
||||
return a.distance - b.distance;
|
||||
|
||||
};
|
||||
|
||||
var intersectObject = function ( object, raycaster, intersects, recursive ) {
|
||||
|
||||
object.raycast( raycaster, intersects );
|
||||
|
||||
if ( recursive === true ) {
|
||||
|
||||
var children = object.children;
|
||||
|
||||
for ( var i = 0, l = children.length; i < l; i ++ ) {
|
||||
|
||||
intersectObject( children[ i ], raycaster, intersects, true );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
THREE.Raycaster.prototype = {
|
||||
|
||||
constructor: THREE.Raycaster,
|
||||
|
||||
precision: 0.0001,
|
||||
linePrecision: 1,
|
||||
|
||||
set: function ( origin, direction ) {
|
||||
|
||||
this.ray.set( origin, direction );
|
||||
// direction is assumed to be normalized (for accurate distance calculations)
|
||||
|
||||
},
|
||||
|
||||
intersectObject: function ( object, recursive ) {
|
||||
|
||||
var intersects = [];
|
||||
|
||||
intersectObject( object, this, intersects, recursive );
|
||||
|
||||
intersects.sort( descSort );
|
||||
|
||||
return intersects;
|
||||
|
||||
},
|
||||
|
||||
intersectObjects: function ( objects, recursive ) {
|
||||
|
||||
var intersects = [];
|
||||
|
||||
for ( var i = 0, l = objects.length; i < l; i ++ ) {
|
||||
|
||||
intersectObject( objects[ i ], this, intersects, recursive );
|
||||
|
||||
}
|
||||
|
||||
intersects.sort( descSort );
|
||||
|
||||
return intersects;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}( THREE ) );
|
||||
|
|
@ -1,470 +0,0 @@
|
|||
/**
|
||||
* @author zz85 / http://www.lab4games.net/zz85/blog
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*
|
||||
* For Text operations in three.js (See TextGeometry)
|
||||
*
|
||||
* 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.FontUtils = {
|
||||
|
||||
faces: {},
|
||||
|
||||
// Just for now. face[weight][style]
|
||||
|
||||
face: 'helvetiker',
|
||||
weight: 'normal',
|
||||
style: 'normal',
|
||||
size: 150,
|
||||
divisions: 10,
|
||||
|
||||
getFace: function () {
|
||||
|
||||
try {
|
||||
|
||||
return this.faces[ this.face ][ this.weight ][ this.style ];
|
||||
|
||||
} catch (e) {
|
||||
|
||||
throw "The font " + this.face + " with " + this.weight + " weight and " + this.style + " style is missing."
|
||||
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
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;
|
||||
|
||||
},
|
||||
|
||||
drawText: function ( text ) {
|
||||
|
||||
var characterPts = [], allPts = [];
|
||||
|
||||
// RenderText
|
||||
|
||||
var i, p,
|
||||
face = this.getFace(),
|
||||
scale = this.size / face.resolution,
|
||||
offset = 0,
|
||||
chars = String( text ).split( '' ),
|
||||
length = chars.length;
|
||||
|
||||
var fontPaths = [];
|
||||
|
||||
for ( i = 0; i < length; i ++ ) {
|
||||
|
||||
var path = new THREE.Path();
|
||||
|
||||
var ret = this.extractGlyphPoints( chars[ i ], face, scale, offset, path );
|
||||
offset += ret.offset;
|
||||
|
||||
fontPaths.push( ret.path );
|
||||
|
||||
}
|
||||
|
||||
// get the width
|
||||
|
||||
var width = offset / 2;
|
||||
//
|
||||
// for ( p = 0; p < allPts.length; p++ ) {
|
||||
//
|
||||
// allPts[ p ].x -= width;
|
||||
//
|
||||
// }
|
||||
|
||||
//var extract = this.extractPoints( allPts, characterPts );
|
||||
//extract.contour = allPts;
|
||||
|
||||
//extract.paths = fontPaths;
|
||||
//extract.offset = width;
|
||||
|
||||
return { paths: fontPaths, offset: width };
|
||||
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
extractGlyphPoints: function ( c, face, scale, offset, path ) {
|
||||
|
||||
var pts = [];
|
||||
|
||||
var i, i2, divisions,
|
||||
outline, action, length,
|
||||
scaleX, scaleY,
|
||||
x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2,
|
||||
laste,
|
||||
glyph = face.glyphs[ c ] || face.glyphs[ '?' ];
|
||||
|
||||
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 ++ ];
|
||||
|
||||
//console.log( action );
|
||||
|
||||
switch ( action ) {
|
||||
|
||||
case 'm':
|
||||
|
||||
// Move To
|
||||
|
||||
x = outline[ i ++ ] * scaleX + offset;
|
||||
y = outline[ i ++ ] * scaleY;
|
||||
|
||||
path.moveTo( x, y );
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
|
||||
// Line To
|
||||
|
||||
x = outline[ i ++ ] * scaleX + offset;
|
||||
y = outline[ i ++ ] * scaleY;
|
||||
path.lineTo( x,y );
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
|
||||
// QuadraticCurveTo
|
||||
|
||||
cpx = outline[ i ++ ] * scaleX + offset;
|
||||
cpy = outline[ i ++ ] * scaleY;
|
||||
cpx1 = outline[ i ++ ] * scaleX + offset;
|
||||
cpy1 = outline[ i ++ ] * scaleY;
|
||||
|
||||
path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
|
||||
|
||||
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.Shape.utils.b2( t, cpx0, cpx1, cpx );
|
||||
var ty = THREE.Shape.utils.b2( t, cpy0, cpy1, cpy );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
|
||||
|
||||
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.Shape.utils.b3( t, cpx0, cpx1, cpx2, cpx );
|
||||
var ty = THREE.Shape.utils.b3( t, cpy0, cpy1, cpy2, cpy );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return { offset: glyph.ha * scale, path:path };
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
THREE.FontUtils.generateShapes = function ( text, parameters ) {
|
||||
|
||||
// Parameters
|
||||
|
||||
parameters = parameters || {};
|
||||
|
||||
var size = parameters.size !== undefined ? parameters.size : 100;
|
||||
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';
|
||||
|
||||
THREE.FontUtils.size = size;
|
||||
THREE.FontUtils.divisions = curveSegments;
|
||||
|
||||
THREE.FontUtils.face = font;
|
||||
THREE.FontUtils.weight = weight;
|
||||
THREE.FontUtils.style = style;
|
||||
|
||||
// Get a Font data json object
|
||||
|
||||
var data = THREE.FontUtils.drawText( text );
|
||||
|
||||
var paths = data.paths;
|
||||
var shapes = [];
|
||||
|
||||
for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
|
||||
|
||||
Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
|
||||
|
||||
}
|
||||
|
||||
return shapes;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
// Sometimes warning is fine, especially polygons are triangulated in reverse.
|
||||
console.log( 'Warning, unable to triangulate polygon!' );
|
||||
|
||||
if ( indices ) return vertIndices;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/* three consecutive vertices in current polygon, <u,v,w> */
|
||||
|
||||
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 ],
|
||||
contour[ b ],
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
var aX, aY, bX, bY, cX, cY;
|
||||
var apx, apy, 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;
|
||||
|
||||
for ( p = 0; p < n; p ++ ) {
|
||||
|
||||
px = contour[ verts[ p ] ].x
|
||||
py = contour[ verts[ p ] ].y
|
||||
|
||||
if ( ( ( px === ax ) && ( py === ay ) ) ||
|
||||
( ( px === bx ) && ( py === by ) ) ||
|
||||
( ( px === cx ) && ( py === cy ) ) ) continue;
|
||||
|
||||
apx = px - ax; apy = py - ay;
|
||||
bpx = px - bx; bpy = py - by;
|
||||
cpx = px - cx; cpy = py - cy;
|
||||
|
||||
// see if p is inside triangle abc
|
||||
|
||||
aCROSSbp = aX * bpy - aY * bpx;
|
||||
cCROSSap = cX * apy - cY * apx;
|
||||
bCROSScp = bX * cpy - bY * cpx;
|
||||
|
||||
if ( ( aCROSSbp >= - EPSILON ) && ( bCROSScp >= - EPSILON ) && ( cCROSSap >= - EPSILON ) ) 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
|
||||
self._typeface_js = { faces: THREE.FontUtils.faces, loadFace: THREE.FontUtils.loadFace };
|
||||
THREE.typeface_js = self._typeface_js;
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.GeometryUtils = {
|
||||
|
||||
merge: function ( geometry1, geometry2, materialIndexOffset ) {
|
||||
|
||||
console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
|
||||
|
||||
var matrix;
|
||||
|
||||
if ( geometry2 instanceof THREE.Mesh ) {
|
||||
|
||||
geometry2.matrixAutoUpdate && geometry2.updateMatrix();
|
||||
|
||||
matrix = geometry2.matrix;
|
||||
geometry2 = geometry2.geometry;
|
||||
|
||||
}
|
||||
|
||||
geometry1.merge( geometry2, matrix, materialIndexOffset );
|
||||
|
||||
},
|
||||
|
||||
center: function ( geometry ) {
|
||||
|
||||
console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
|
||||
return geometry.center();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author Daosheng Mu / https://github.com/DaoshengMu/
|
||||
*/
|
||||
|
||||
THREE.ImageUtils = {
|
||||
|
||||
crossOrigin: undefined,
|
||||
|
||||
loadTexture: function ( url, mapping, onLoad, onError ) {
|
||||
|
||||
var loader = new THREE.ImageLoader();
|
||||
loader.crossOrigin = this.crossOrigin;
|
||||
|
||||
var texture = new THREE.Texture( undefined, mapping );
|
||||
|
||||
loader.load( url, function ( image ) {
|
||||
|
||||
texture.image = image;
|
||||
texture.needsUpdate = true;
|
||||
|
||||
if ( onLoad ) onLoad( texture );
|
||||
|
||||
}, undefined, function ( event ) {
|
||||
|
||||
if ( onError ) onError( event );
|
||||
|
||||
} );
|
||||
|
||||
texture.sourceFile = url;
|
||||
|
||||
return texture;
|
||||
|
||||
},
|
||||
|
||||
loadTextureCube: function ( array, mapping, onLoad, onError ) {
|
||||
|
||||
var images = [];
|
||||
|
||||
var loader = new THREE.ImageLoader();
|
||||
loader.crossOrigin = this.crossOrigin;
|
||||
|
||||
var texture = new THREE.CubeTexture( images, mapping );
|
||||
|
||||
// no flipping needed for cube textures
|
||||
|
||||
texture.flipY = false;
|
||||
|
||||
var loaded = 0;
|
||||
|
||||
var loadTexture = function ( i ) {
|
||||
|
||||
loader.load( array[ i ], function ( image ) {
|
||||
|
||||
texture.images[ i ] = image;
|
||||
|
||||
loaded += 1;
|
||||
|
||||
if ( loaded === 6 ) {
|
||||
|
||||
texture.needsUpdate = true;
|
||||
|
||||
if ( onLoad ) onLoad( texture );
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
for ( var i = 0, il = array.length; i < il; ++ i ) {
|
||||
|
||||
loadTexture( i );
|
||||
|
||||
}
|
||||
|
||||
return texture;
|
||||
|
||||
},
|
||||
|
||||
loadCompressedTexture: function () {
|
||||
|
||||
console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' )
|
||||
|
||||
},
|
||||
|
||||
loadCompressedTextureCube: function () {
|
||||
|
||||
console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' )
|
||||
|
||||
},
|
||||
|
||||
getNormalMap: function ( image, depth ) {
|
||||
|
||||
// Adapted from http://www.paulbrunt.co.uk/lab/heightnormal/
|
||||
|
||||
var cross = function ( a, b ) {
|
||||
|
||||
return [ a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ], a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ], a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ] ];
|
||||
|
||||
}
|
||||
|
||||
var subtract = function ( a, b ) {
|
||||
|
||||
return [ a[ 0 ] - b[ 0 ], a[ 1 ] - b[ 1 ], a[ 2 ] - b[ 2 ] ];
|
||||
|
||||
}
|
||||
|
||||
var normalize = function ( a ) {
|
||||
|
||||
var l = Math.sqrt( a[ 0 ] * a[ 0 ] + a[ 1 ] * a[ 1 ] + a[ 2 ] * a[ 2 ] );
|
||||
return [ a[ 0 ] / l, a[ 1 ] / l, a[ 2 ] / l ];
|
||||
|
||||
}
|
||||
|
||||
depth = depth | 1;
|
||||
|
||||
var width = image.width;
|
||||
var height = image.height;
|
||||
|
||||
var canvas = document.createElement( 'canvas' );
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
var context = canvas.getContext( '2d' );
|
||||
context.drawImage( image, 0, 0 );
|
||||
|
||||
var data = context.getImageData( 0, 0, width, height ).data;
|
||||
var imageData = context.createImageData( width, height );
|
||||
var output = imageData.data;
|
||||
|
||||
for ( var x = 0; x < width; x ++ ) {
|
||||
|
||||
for ( var y = 0; y < height; y ++ ) {
|
||||
|
||||
var ly = y - 1 < 0 ? 0 : y - 1;
|
||||
var uy = y + 1 > height - 1 ? height - 1 : y + 1;
|
||||
var lx = x - 1 < 0 ? 0 : x - 1;
|
||||
var ux = x + 1 > width - 1 ? width - 1 : x + 1;
|
||||
|
||||
var points = [];
|
||||
var origin = [ 0, 0, data[ ( y * width + x ) * 4 ] / 255 * depth ];
|
||||
points.push( [ - 1, 0, data[ ( y * width + lx ) * 4 ] / 255 * depth ] );
|
||||
points.push( [ - 1, - 1, data[ ( ly * width + lx ) * 4 ] / 255 * depth ] );
|
||||
points.push( [ 0, - 1, data[ ( ly * width + x ) * 4 ] / 255 * depth ] );
|
||||
points.push( [ 1, - 1, data[ ( ly * width + ux ) * 4 ] / 255 * depth ] );
|
||||
points.push( [ 1, 0, data[ ( y * width + ux ) * 4 ] / 255 * depth ] );
|
||||
points.push( [ 1, 1, data[ ( uy * width + ux ) * 4 ] / 255 * depth ] );
|
||||
points.push( [ 0, 1, data[ ( uy * width + x ) * 4 ] / 255 * depth ] );
|
||||
points.push( [ - 1, 1, data[ ( uy * width + lx ) * 4 ] / 255 * depth ] );
|
||||
|
||||
var normals = [];
|
||||
var num_points = points.length;
|
||||
|
||||
for ( var i = 0; i < num_points; i ++ ) {
|
||||
|
||||
var v1 = points[ i ];
|
||||
var v2 = points[ ( i + 1 ) % num_points ];
|
||||
v1 = subtract( v1, origin );
|
||||
v2 = subtract( v2, origin );
|
||||
normals.push( normalize( cross( v1, v2 ) ) );
|
||||
|
||||
}
|
||||
|
||||
var normal = [ 0, 0, 0 ];
|
||||
|
||||
for ( var i = 0; i < normals.length; i ++ ) {
|
||||
|
||||
normal[ 0 ] += normals[ i ][ 0 ];
|
||||
normal[ 1 ] += normals[ i ][ 1 ];
|
||||
normal[ 2 ] += normals[ i ][ 2 ];
|
||||
|
||||
}
|
||||
|
||||
normal[ 0 ] /= normals.length;
|
||||
normal[ 1 ] /= normals.length;
|
||||
normal[ 2 ] /= normals.length;
|
||||
|
||||
var idx = ( y * width + x ) * 4;
|
||||
|
||||
output[ idx ] = ( ( normal[ 0 ] + 1.0 ) / 2.0 * 255 ) | 0;
|
||||
output[ idx + 1 ] = ( ( normal[ 1 ] + 1.0 ) / 2.0 * 255 ) | 0;
|
||||
output[ idx + 2 ] = ( normal[ 2 ] * 255 ) | 0;
|
||||
output[ idx + 3 ] = 255;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
context.putImageData( imageData, 0, 0 );
|
||||
|
||||
return canvas;
|
||||
|
||||
},
|
||||
|
||||
generateDataTexture: function ( width, height, color ) {
|
||||
|
||||
var size = width * height;
|
||||
var data = new Uint8Array( 3 * size );
|
||||
|
||||
var r = Math.floor( color.r * 255 );
|
||||
var g = Math.floor( color.g * 255 );
|
||||
var b = Math.floor( color.b * 255 );
|
||||
|
||||
for ( var i = 0; i < size; i ++ ) {
|
||||
|
||||
data[ i * 3 ] = r;
|
||||
data[ i * 3 + 1 ] = g;
|
||||
data[ i * 3 + 2 ] = b;
|
||||
|
||||
}
|
||||
|
||||
var texture = new THREE.DataTexture( data, width, height, THREE.RGBFormat );
|
||||
texture.needsUpdate = true;
|
||||
|
||||
return texture;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.SceneUtils = {
|
||||
|
||||
createMultiMaterialObject: function ( geometry, materials ) {
|
||||
|
||||
var group = new THREE.Object3D();
|
||||
|
||||
for ( var i = 0, l = materials.length; i < l; i ++ ) {
|
||||
|
||||
group.add( new THREE.Mesh( geometry, materials[ i ] ) );
|
||||
|
||||
}
|
||||
|
||||
return group;
|
||||
|
||||
},
|
||||
|
||||
detach: function ( child, parent, scene ) {
|
||||
|
||||
child.applyMatrix( parent.matrixWorld );
|
||||
parent.remove( child );
|
||||
scene.add( child );
|
||||
|
||||
},
|
||||
|
||||
attach: function ( child, scene, parent ) {
|
||||
|
||||
var matrixWorldInverse = new THREE.Matrix4();
|
||||
matrixWorldInverse.getInverse( parent.matrixWorld );
|
||||
child.applyMatrix( matrixWorldInverse );
|
||||
|
||||
scene.remove( child );
|
||||
parent.add( child );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,402 +0,0 @@
|
|||
/**
|
||||
* @author mikael emtinger / http://gomo.se/
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.Animation = function ( root, data ) {
|
||||
|
||||
this.root = root;
|
||||
this.data = THREE.AnimationHandler.init( data );
|
||||
this.hierarchy = THREE.AnimationHandler.parse( root );
|
||||
|
||||
this.currentTime = 0;
|
||||
this.timeScale = 1;
|
||||
|
||||
this.isPlaying = false;
|
||||
this.loop = true;
|
||||
this.weight = 0;
|
||||
|
||||
this.interpolationType = THREE.AnimationHandler.LINEAR;
|
||||
|
||||
};
|
||||
|
||||
|
||||
THREE.Animation.prototype.keyTypes = [ "pos", "rot", "scl" ];
|
||||
|
||||
|
||||
THREE.Animation.prototype.play = function ( startTime, weight ) {
|
||||
|
||||
this.currentTime = startTime !== undefined ? startTime : 0;
|
||||
this.weight = weight !== undefined ? weight: 1;
|
||||
|
||||
this.isPlaying = true;
|
||||
|
||||
this.reset();
|
||||
|
||||
THREE.AnimationHandler.play( this );
|
||||
|
||||
};
|
||||
|
||||
|
||||
THREE.Animation.prototype.stop = function() {
|
||||
|
||||
this.isPlaying = false;
|
||||
|
||||
THREE.AnimationHandler.stop( this );
|
||||
|
||||
};
|
||||
|
||||
THREE.Animation.prototype.reset = function () {
|
||||
|
||||
for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
|
||||
|
||||
var object = this.hierarchy[ h ];
|
||||
|
||||
object.matrixAutoUpdate = true;
|
||||
|
||||
if ( object.animationCache === undefined ) {
|
||||
|
||||
object.animationCache = {};
|
||||
|
||||
}
|
||||
|
||||
if ( object.animationCache[this.data.name] === undefined ) {
|
||||
|
||||
object.animationCache[this.data.name] = {};
|
||||
object.animationCache[this.data.name].prevKey = { pos: 0, rot: 0, scl: 0 };
|
||||
object.animationCache[this.data.name].nextKey = { pos: 0, rot: 0, scl: 0 };
|
||||
object.animationCache[this.data.name].originalMatrix = object.matrix;
|
||||
|
||||
}
|
||||
|
||||
var animationCache = object.animationCache[this.data.name];
|
||||
|
||||
// Get keys to match our current time
|
||||
|
||||
for ( var t = 0; t < 3; t ++ ) {
|
||||
|
||||
var type = this.keyTypes[ t ];
|
||||
|
||||
var prevKey = this.data.hierarchy[ h ].keys[ 0 ];
|
||||
var nextKey = this.getNextKeyWith( type, h, 1 );
|
||||
|
||||
while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
|
||||
|
||||
prevKey = nextKey;
|
||||
nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
|
||||
|
||||
}
|
||||
|
||||
animationCache.prevKey[ type ] = prevKey;
|
||||
animationCache.nextKey[ type ] = nextKey;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
THREE.Animation.prototype.update = (function(){
|
||||
|
||||
var points = [];
|
||||
var target = new THREE.Vector3();
|
||||
var newVector = new THREE.Vector3();
|
||||
var newQuat = new THREE.Quaternion();
|
||||
|
||||
// Catmull-Rom spline
|
||||
|
||||
var 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 ] = interpolate( pa[ 0 ], pb[ 0 ], pc[ 0 ], pd[ 0 ], weight, w2, w3 );
|
||||
v3[ 1 ] = interpolate( pa[ 1 ], pb[ 1 ], pc[ 1 ], pd[ 1 ], weight, w2, w3 );
|
||||
v3[ 2 ] = interpolate( pa[ 2 ], pb[ 2 ], pc[ 2 ], pd[ 2 ], weight, w2, w3 );
|
||||
|
||||
return v3;
|
||||
|
||||
};
|
||||
|
||||
var 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;
|
||||
|
||||
};
|
||||
|
||||
return function ( delta ) {
|
||||
|
||||
if ( this.isPlaying === false ) return;
|
||||
|
||||
this.currentTime += delta * this.timeScale;
|
||||
|
||||
if ( this.weight === 0 )
|
||||
return;
|
||||
|
||||
//
|
||||
|
||||
var duration = this.data.length;
|
||||
|
||||
if ( this.loop === true && this.currentTime > duration ) {
|
||||
|
||||
this.currentTime %= duration;
|
||||
this.reset();
|
||||
|
||||
} else if ( this.loop === false && this.currentTime > duration ) {
|
||||
|
||||
this.stop();
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
|
||||
|
||||
var object = this.hierarchy[ h ];
|
||||
var animationCache = object.animationCache[this.data.name];
|
||||
|
||||
// loop through pos/rot/scl
|
||||
|
||||
for ( var t = 0; t < 3; t ++ ) {
|
||||
|
||||
// get keys
|
||||
|
||||
var type = this.keyTypes[ t ];
|
||||
var prevKey = animationCache.prevKey[ type ];
|
||||
var nextKey = animationCache.nextKey[ type ];
|
||||
|
||||
if ( nextKey.time <= this.currentTime ) {
|
||||
|
||||
prevKey = this.data.hierarchy[ h ].keys[ 0 ];
|
||||
nextKey = this.getNextKeyWith( type, h, 1 );
|
||||
|
||||
while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
|
||||
|
||||
prevKey = nextKey;
|
||||
nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
|
||||
|
||||
}
|
||||
|
||||
animationCache.prevKey[ type ] = prevKey;
|
||||
animationCache.nextKey[ type ] = nextKey;
|
||||
|
||||
}
|
||||
|
||||
object.matrixAutoUpdate = true;
|
||||
object.matrixWorldNeedsUpdate = true;
|
||||
|
||||
var scale = ( this.currentTime - prevKey.time ) / ( nextKey.time - prevKey.time );
|
||||
|
||||
var prevXYZ = prevKey[ type ];
|
||||
var nextXYZ = nextKey[ type ];
|
||||
|
||||
if ( scale < 0 ) scale = 0;
|
||||
if ( scale > 1 ) scale = 1;
|
||||
|
||||
// interpolate
|
||||
|
||||
if ( type === "pos" ) {
|
||||
|
||||
if ( this.interpolationType === THREE.AnimationHandler.LINEAR ) {
|
||||
|
||||
newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
|
||||
newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
|
||||
newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
|
||||
|
||||
// blend
|
||||
if ( object instanceof THREE.Bone ) {
|
||||
|
||||
var proportionalWeight = this.weight / ( this.weight + object.accumulatedPosWeight );
|
||||
object.position.lerp( newVector, proportionalWeight );
|
||||
object.accumulatedPosWeight += this.weight;
|
||||
|
||||
} else {
|
||||
|
||||
object.position.copy( newVector );
|
||||
|
||||
}
|
||||
|
||||
} else if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
|
||||
this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
|
||||
|
||||
points[ 0 ] = this.getPrevKeyWith( "pos", h, prevKey.index - 1 )[ "pos" ];
|
||||
points[ 1 ] = prevXYZ;
|
||||
points[ 2 ] = nextXYZ;
|
||||
points[ 3 ] = this.getNextKeyWith( "pos", h, nextKey.index + 1 )[ "pos" ];
|
||||
|
||||
scale = scale * 0.33 + 0.33;
|
||||
|
||||
var currentPoint = interpolateCatmullRom( points, scale );
|
||||
var proportionalWeight = 1;
|
||||
|
||||
if ( object instanceof THREE.Bone ) {
|
||||
|
||||
proportionalWeight = this.weight / ( this.weight + object.accumulatedPosWeight );
|
||||
object.accumulatedPosWeight += this.weight;
|
||||
|
||||
}
|
||||
|
||||
// blend
|
||||
|
||||
var vector = object.position;
|
||||
|
||||
vector.x = vector.x + ( currentPoint[ 0 ] - vector.x ) * proportionalWeight;
|
||||
vector.y = vector.y + ( currentPoint[ 1 ] - vector.y ) * proportionalWeight;
|
||||
vector.z = vector.z + ( currentPoint[ 2 ] - vector.z ) * proportionalWeight;
|
||||
|
||||
if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
|
||||
|
||||
var forwardPoint = interpolateCatmullRom( points, scale * 1.01 );
|
||||
|
||||
target.set( forwardPoint[ 0 ], forwardPoint[ 1 ], forwardPoint[ 2 ] );
|
||||
target.sub( vector );
|
||||
target.y = 0;
|
||||
target.normalize();
|
||||
|
||||
var angle = Math.atan2( target.x, target.z );
|
||||
object.rotation.set( 0, angle, 0 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( type === "rot" ) {
|
||||
|
||||
THREE.Quaternion.slerp( prevXYZ, nextXYZ, newQuat, scale );
|
||||
|
||||
// Avoid paying the cost of an additional slerp if we don't have to
|
||||
if ( ! ( object instanceof THREE.Bone ) ) {
|
||||
|
||||
object.quaternion.copy(newQuat);
|
||||
|
||||
} else if ( object.accumulatedRotWeight === 0 ) {
|
||||
|
||||
object.quaternion.copy(newQuat);
|
||||
object.accumulatedRotWeight = this.weight;
|
||||
|
||||
} else {
|
||||
|
||||
var proportionalWeight = this.weight / ( this.weight + object.accumulatedRotWeight );
|
||||
THREE.Quaternion.slerp( object.quaternion, newQuat, object.quaternion, proportionalWeight );
|
||||
object.accumulatedRotWeight += this.weight;
|
||||
|
||||
}
|
||||
|
||||
} else if ( type === "scl" ) {
|
||||
|
||||
newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
|
||||
newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
|
||||
newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
|
||||
|
||||
if ( object instanceof THREE.Bone ) {
|
||||
|
||||
var proportionalWeight = this.weight / ( this.weight + object.accumulatedSclWeight);
|
||||
object.scale.lerp( newVector, proportionalWeight );
|
||||
object.accumulatedSclWeight += this.weight;
|
||||
|
||||
} else {
|
||||
|
||||
object.scale.copy( newVector );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 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 ];
|
||||
|
||||
};
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
/**
|
||||
* @author mikael emtinger / http://gomo.se/
|
||||
*/
|
||||
|
||||
THREE.AnimationHandler = {
|
||||
|
||||
LINEAR: 0,
|
||||
CATMULLROM: 1,
|
||||
CATMULLROM_FORWARD: 2,
|
||||
|
||||
//
|
||||
|
||||
add: function () { console.warn( 'THREE.AnimationHandler.add() has been deprecated.' ); },
|
||||
get: function () { console.warn( 'THREE.AnimationHandler.get() has been deprecated.' ); },
|
||||
remove: function () { console.warn( 'THREE.AnimationHandler.remove() has been deprecated.' ); },
|
||||
|
||||
//
|
||||
|
||||
animations: [],
|
||||
|
||||
init: 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().fromArray( quat );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// prepare morph target keys
|
||||
|
||||
if ( data.hierarchy[ h ].keys.length && 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 = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
|
||||
|
||||
data.hierarchy[ h ].keys[ k ].index = k;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data.initialized = true;
|
||||
|
||||
return data;
|
||||
|
||||
},
|
||||
|
||||
parse: function ( root ) {
|
||||
|
||||
var parseRecurseHierarchy = function ( root, hierarchy ) {
|
||||
|
||||
hierarchy.push( root );
|
||||
|
||||
for ( var c = 0; c < root.children.length; c ++ )
|
||||
parseRecurseHierarchy( root.children[ c ], hierarchy );
|
||||
|
||||
};
|
||||
|
||||
// setup hierarchy
|
||||
|
||||
var hierarchy = [];
|
||||
|
||||
if ( root instanceof THREE.SkinnedMesh ) {
|
||||
|
||||
for ( var b = 0; b < root.skeleton.bones.length; b ++ ) {
|
||||
|
||||
hierarchy.push( root.skeleton.bones[ b ] );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
parseRecurseHierarchy( root, hierarchy );
|
||||
|
||||
}
|
||||
|
||||
return hierarchy;
|
||||
|
||||
},
|
||||
|
||||
play: function ( animation ) {
|
||||
|
||||
if ( this.animations.indexOf( animation ) === - 1 ) {
|
||||
|
||||
this.animations.push( animation );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
stop: function ( animation ) {
|
||||
|
||||
var index = this.animations.indexOf( animation );
|
||||
|
||||
if ( index !== - 1 ) {
|
||||
|
||||
this.animations.splice( index, 1 );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
update: function ( deltaTimeMS ) {
|
||||
|
||||
for ( var i = 0; i < this.animations.length; i ++ ) {
|
||||
|
||||
this.animations[ i ].update( deltaTimeMS );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,244 +0,0 @@
|
|||
/**
|
||||
* @author mikael emtinger / http://gomo.se/
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
* @author khang duong
|
||||
* @author erik kitson
|
||||
*/
|
||||
|
||||
THREE.KeyFrameAnimation = function ( data ) {
|
||||
|
||||
this.root = data.node;
|
||||
this.data = THREE.AnimationHandler.init( data );
|
||||
this.hierarchy = THREE.AnimationHandler.parse( this.root );
|
||||
this.currentTime = 0;
|
||||
this.timeScale = 0.001;
|
||||
this.isPlaying = false;
|
||||
this.isPaused = true;
|
||||
this.loop = true;
|
||||
|
||||
// initialize to first keyframes
|
||||
|
||||
for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
|
||||
|
||||
var keys = this.data.hierarchy[h].keys,
|
||||
sids = this.data.hierarchy[h].sids,
|
||||
obj = this.hierarchy[h];
|
||||
|
||||
if ( keys.length && sids ) {
|
||||
|
||||
for ( var s = 0; s < sids.length; s ++ ) {
|
||||
|
||||
var sid = sids[ s ],
|
||||
next = this.getNextKeyWith( sid, h, 0 );
|
||||
|
||||
if ( next ) {
|
||||
|
||||
next.apply( sid );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
obj.matrixAutoUpdate = false;
|
||||
this.data.hierarchy[h].node.updateMatrix();
|
||||
obj.matrixWorldNeedsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
THREE.KeyFrameAnimation.prototype.play = function ( startTime ) {
|
||||
|
||||
this.currentTime = startTime !== undefined ? startTime : 0;
|
||||
|
||||
if ( this.isPlaying === false ) {
|
||||
|
||||
this.isPlaying = true;
|
||||
|
||||
// reset key cache
|
||||
|
||||
var h, hl = this.hierarchy.length,
|
||||
object,
|
||||
node;
|
||||
|
||||
for ( h = 0; h < hl; h ++ ) {
|
||||
|
||||
object = this.hierarchy[ h ];
|
||||
node = this.data.hierarchy[ h ];
|
||||
|
||||
if ( node.animationCache === undefined ) {
|
||||
|
||||
node.animationCache = {};
|
||||
node.animationCache.prevKey = null;
|
||||
node.animationCache.nextKey = null;
|
||||
node.animationCache.originalMatrix = object.matrix;
|
||||
|
||||
}
|
||||
|
||||
var keys = this.data.hierarchy[h].keys;
|
||||
|
||||
if (keys.length) {
|
||||
|
||||
node.animationCache.prevKey = keys[ 0 ];
|
||||
node.animationCache.nextKey = keys[ 1 ];
|
||||
|
||||
this.startTime = Math.min( keys[0].time, this.startTime );
|
||||
this.endTime = Math.max( keys[keys.length - 1].time, this.endTime );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.update( 0 );
|
||||
|
||||
}
|
||||
|
||||
this.isPaused = false;
|
||||
|
||||
THREE.AnimationHandler.play( this );
|
||||
|
||||
};
|
||||
|
||||
|
||||
THREE.KeyFrameAnimation.prototype.stop = function() {
|
||||
|
||||
this.isPlaying = false;
|
||||
this.isPaused = false;
|
||||
|
||||
THREE.AnimationHandler.stop( this );
|
||||
|
||||
// reset JIT matrix and remove cache
|
||||
|
||||
for ( var h = 0; h < this.data.hierarchy.length; h ++ ) {
|
||||
|
||||
var obj = this.hierarchy[ h ];
|
||||
var node = this.data.hierarchy[ h ];
|
||||
|
||||
if ( node.animationCache !== undefined ) {
|
||||
|
||||
var original = node.animationCache.originalMatrix;
|
||||
|
||||
original.copy( obj.matrix );
|
||||
obj.matrix = original;
|
||||
|
||||
delete node.animationCache;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Update
|
||||
|
||||
THREE.KeyFrameAnimation.prototype.update = function ( delta ) {
|
||||
|
||||
if ( this.isPlaying === false ) return;
|
||||
|
||||
this.currentTime += delta * this.timeScale;
|
||||
|
||||
//
|
||||
|
||||
var duration = this.data.length;
|
||||
|
||||
if ( this.loop === true && this.currentTime > duration ) {
|
||||
|
||||
this.currentTime %= duration;
|
||||
|
||||
}
|
||||
|
||||
this.currentTime = Math.min( this.currentTime, duration );
|
||||
|
||||
for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
|
||||
|
||||
var object = this.hierarchy[ h ];
|
||||
var node = this.data.hierarchy[ h ];
|
||||
|
||||
var keys = node.keys,
|
||||
animationCache = node.animationCache;
|
||||
|
||||
|
||||
if ( keys.length ) {
|
||||
|
||||
var prevKey = animationCache.prevKey;
|
||||
var nextKey = animationCache.nextKey;
|
||||
|
||||
if ( nextKey.time <= this.currentTime ) {
|
||||
|
||||
while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
|
||||
|
||||
prevKey = nextKey;
|
||||
nextKey = keys[ prevKey.index + 1 ];
|
||||
|
||||
}
|
||||
|
||||
animationCache.prevKey = prevKey;
|
||||
animationCache.nextKey = nextKey;
|
||||
|
||||
}
|
||||
|
||||
if ( nextKey.time >= this.currentTime ) {
|
||||
|
||||
prevKey.interpolate( nextKey, this.currentTime );
|
||||
|
||||
} else {
|
||||
|
||||
prevKey.interpolate( nextKey, nextKey.time );
|
||||
|
||||
}
|
||||
|
||||
this.data.hierarchy[ h ].node.updateMatrix();
|
||||
object.matrixWorldNeedsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Get next key with
|
||||
|
||||
THREE.KeyFrameAnimation.prototype.getNextKeyWith = function( sid, h, key ) {
|
||||
|
||||
var keys = this.data.hierarchy[ h ].keys;
|
||||
key = key % keys.length;
|
||||
|
||||
for ( ; key < keys.length; key ++ ) {
|
||||
|
||||
if ( keys[ key ].hasTarget( sid ) ) {
|
||||
|
||||
return keys[ key ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return keys[ 0 ];
|
||||
|
||||
};
|
||||
|
||||
// Get previous key with
|
||||
|
||||
THREE.KeyFrameAnimation.prototype.getPrevKeyWith = function( sid, h, key ) {
|
||||
|
||||
var keys = this.data.hierarchy[ h ].keys;
|
||||
key = key >= 0 ? key : key + keys.length;
|
||||
|
||||
for ( ; key >= 0; key -- ) {
|
||||
|
||||
if ( keys[ key ].hasTarget( sid ) ) {
|
||||
|
||||
return keys[ key ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return keys[ keys.length - 1 ];
|
||||
|
||||
};
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com
|
||||
*/
|
||||
|
||||
THREE.MorphAnimation = function ( mesh ) {
|
||||
|
||||
this.mesh = mesh;
|
||||
this.frames = mesh.morphTargetInfluences.length;
|
||||
this.currentTime = 0;
|
||||
this.duration = 1000;
|
||||
this.loop = true;
|
||||
|
||||
this.isPlaying = false;
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphAnimation.prototype = {
|
||||
|
||||
play: function () {
|
||||
|
||||
this.isPlaying = true;
|
||||
|
||||
},
|
||||
|
||||
pause: function () {
|
||||
|
||||
this.isPlaying = false;
|
||||
|
||||
},
|
||||
|
||||
update: ( function () {
|
||||
|
||||
var lastFrame = 0;
|
||||
var currentFrame = 0;
|
||||
|
||||
return function ( delta ) {
|
||||
|
||||
if ( this.isPlaying === false ) return;
|
||||
|
||||
this.currentTime += delta;
|
||||
|
||||
if ( this.loop === true && this.currentTime > this.duration ) {
|
||||
|
||||
this.currentTime %= this.duration;
|
||||
|
||||
}
|
||||
|
||||
this.currentTime = Math.min( this.currentTime, this.duration );
|
||||
|
||||
var interpolation = this.duration / this.frames;
|
||||
var frame = Math.floor( this.currentTime / interpolation );
|
||||
|
||||
if ( frame != currentFrame ) {
|
||||
|
||||
this.mesh.morphTargetInfluences[ lastFrame ] = 0;
|
||||
this.mesh.morphTargetInfluences[ currentFrame ] = 1;
|
||||
this.mesh.morphTargetInfluences[ frame ] = 0;
|
||||
|
||||
lastFrame = currentFrame;
|
||||
currentFrame = frame;
|
||||
|
||||
}
|
||||
|
||||
this.mesh.morphTargetInfluences[ frame ] = ( this.currentTime % interpolation ) / interpolation;
|
||||
this.mesh.morphTargetInfluences[ lastFrame ] = 1 - this.mesh.morphTargetInfluences[ frame ];
|
||||
|
||||
}
|
||||
|
||||
} )()
|
||||
|
||||
};
|
||||
|
|
@ -1,335 +0,0 @@
|
|||
/**
|
||||
* @author zz85 / http://www.lab4games.net/zz85/blog
|
||||
* Extensible curve object
|
||||
*
|
||||
* Some common of Curve methods
|
||||
* .getPoint(t), getTangent(t)
|
||||
* .getPointAt(u), getTagentAt(u)
|
||||
* .getPoints(), .getSpacedPoints()
|
||||
* .getLength()
|
||||
* .updateArcLengths()
|
||||
*
|
||||
* This following classes subclasses THREE.Curve:
|
||||
*
|
||||
* -- 2d classes --
|
||||
* THREE.LineCurve
|
||||
* THREE.QuadraticBezierCurve
|
||||
* THREE.CubicBezierCurve
|
||||
* THREE.SplineCurve
|
||||
* THREE.ArcCurve
|
||||
* THREE.EllipseCurve
|
||||
*
|
||||
* -- 3d classes --
|
||||
* THREE.LineCurve3
|
||||
* THREE.QuadraticBezierCurve3
|
||||
* THREE.CubicBezierCurve3
|
||||
* THREE.SplineCurve3
|
||||
* THREE.ClosedSplineCurve3
|
||||
*
|
||||
* A series of curves can be represented as a THREE.CurvePath
|
||||
*
|
||||
**/
|
||||
|
||||
/**************************************************************
|
||||
* Abstract Curve base class
|
||||
**************************************************************/
|
||||
|
||||
THREE.Curve = function () {
|
||||
|
||||
};
|
||||
|
||||
// Virtual base class method to overwrite and implement in subclasses
|
||||
// - t [0 .. 1]
|
||||
|
||||
THREE.Curve.prototype.getPoint = function ( t ) {
|
||||
|
||||
console.log( "Warning, getPoint() not implemented!" );
|
||||
return null;
|
||||
|
||||
};
|
||||
|
||||
// Get point at relative position in curve according to arc length
|
||||
// - u [0 .. 1]
|
||||
|
||||
THREE.Curve.prototype.getPointAt = function ( u ) {
|
||||
|
||||
var t = this.getUtoTmapping( u );
|
||||
return this.getPoint( t );
|
||||
|
||||
};
|
||||
|
||||
// Get sequence of points using getPoint( t )
|
||||
|
||||
THREE.Curve.prototype.getPoints = function ( divisions ) {
|
||||
|
||||
if ( ! divisions ) divisions = 5;
|
||||
|
||||
var d, pts = [];
|
||||
|
||||
for ( d = 0; d <= divisions; d ++ ) {
|
||||
|
||||
pts.push( this.getPoint( d / divisions ) );
|
||||
|
||||
}
|
||||
|
||||
return pts;
|
||||
|
||||
};
|
||||
|
||||
// Get sequence of points using getPointAt( u )
|
||||
|
||||
THREE.Curve.prototype.getSpacedPoints = function ( divisions ) {
|
||||
|
||||
if ( ! divisions ) divisions = 5;
|
||||
|
||||
var d, pts = [];
|
||||
|
||||
for ( d = 0; d <= divisions; d ++ ) {
|
||||
|
||||
pts.push( this.getPointAt( d / divisions ) );
|
||||
|
||||
}
|
||||
|
||||
return pts;
|
||||
|
||||
};
|
||||
|
||||
// Get total curve arc length
|
||||
|
||||
THREE.Curve.prototype.getLength = function () {
|
||||
|
||||
var lengths = this.getLengths();
|
||||
return lengths[ lengths.length - 1 ];
|
||||
|
||||
};
|
||||
|
||||
// Get list of cumulative segment lengths
|
||||
|
||||
THREE.Curve.prototype.getLengths = function ( divisions ) {
|
||||
|
||||
if ( ! divisions ) divisions = (this.__arcLengthDivisions) ? (this.__arcLengthDivisions): 200;
|
||||
|
||||
if ( this.cacheArcLengths
|
||||
&& ( this.cacheArcLengths.length == divisions + 1 )
|
||||
&& ! this.needsUpdate) {
|
||||
|
||||
//console.log( "cached", this.cacheArcLengths );
|
||||
return this.cacheArcLengths;
|
||||
|
||||
}
|
||||
|
||||
this.needsUpdate = false;
|
||||
|
||||
var cache = [];
|
||||
var current, last = this.getPoint( 0 );
|
||||
var p, sum = 0;
|
||||
|
||||
cache.push( 0 );
|
||||
|
||||
for ( p = 1; p <= divisions; p ++ ) {
|
||||
|
||||
current = this.getPoint ( p / divisions );
|
||||
sum += current.distanceTo( last );
|
||||
cache.push( sum );
|
||||
last = current;
|
||||
|
||||
}
|
||||
|
||||
this.cacheArcLengths = cache;
|
||||
|
||||
return cache; // { sums: cache, sum:sum }; Sum is in the last element.
|
||||
|
||||
};
|
||||
|
||||
|
||||
THREE.Curve.prototype.updateArcLengths = function() {
|
||||
this.needsUpdate = true;
|
||||
this.getLengths();
|
||||
};
|
||||
|
||||
// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equi distance
|
||||
|
||||
THREE.Curve.prototype.getUtoTmapping = function ( u, distance ) {
|
||||
|
||||
var arcLengths = this.getLengths();
|
||||
|
||||
var i = 0, il = arcLengths.length;
|
||||
|
||||
var targetArcLength; // The targeted u distance value to get
|
||||
|
||||
if ( distance ) {
|
||||
|
||||
targetArcLength = distance;
|
||||
|
||||
} else {
|
||||
|
||||
targetArcLength = u * arcLengths[ il - 1 ];
|
||||
|
||||
}
|
||||
|
||||
//var time = Date.now();
|
||||
|
||||
// binary search for the index with largest value smaller than target u distance
|
||||
|
||||
var low = 0, high = il - 1, comparison;
|
||||
|
||||
while ( low <= high ) {
|
||||
|
||||
i = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats
|
||||
|
||||
comparison = arcLengths[ i ] - targetArcLength;
|
||||
|
||||
if ( comparison < 0 ) {
|
||||
|
||||
low = i + 1;
|
||||
continue;
|
||||
|
||||
} else if ( comparison > 0 ) {
|
||||
|
||||
high = i - 1;
|
||||
continue;
|
||||
|
||||
} else {
|
||||
|
||||
high = i;
|
||||
break;
|
||||
|
||||
// DONE
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
i = high;
|
||||
|
||||
//console.log('b' , i, low, high, Date.now()- time);
|
||||
|
||||
if ( arcLengths[ i ] == targetArcLength ) {
|
||||
|
||||
var t = i / ( il - 1 );
|
||||
return t;
|
||||
|
||||
}
|
||||
|
||||
// we could get finer grain at lengths, or use simple interpolatation between two points
|
||||
|
||||
var lengthBefore = arcLengths[ i ];
|
||||
var lengthAfter = arcLengths[ i + 1 ];
|
||||
|
||||
var segmentLength = lengthAfter - lengthBefore;
|
||||
|
||||
// determine where we are between the 'before' and 'after' points
|
||||
|
||||
var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
|
||||
|
||||
// add that fractional amount to t
|
||||
|
||||
var t = ( i + segmentFraction ) / ( il -1 );
|
||||
|
||||
return t;
|
||||
|
||||
};
|
||||
|
||||
// Returns a unit vector tangent at t
|
||||
// In case any sub curve does not implement its tangent derivation,
|
||||
// 2 points a small delta apart will be used to find its gradient
|
||||
// which seems to give a reasonable approximation
|
||||
|
||||
THREE.Curve.prototype.getTangent = function( t ) {
|
||||
|
||||
var delta = 0.0001;
|
||||
var t1 = t - delta;
|
||||
var t2 = t + delta;
|
||||
|
||||
// Capping in case of danger
|
||||
|
||||
if ( t1 < 0 ) t1 = 0;
|
||||
if ( t2 > 1 ) t2 = 1;
|
||||
|
||||
var pt1 = this.getPoint( t1 );
|
||||
var pt2 = this.getPoint( t2 );
|
||||
|
||||
var vec = pt2.clone().sub(pt1);
|
||||
return vec.normalize();
|
||||
|
||||
};
|
||||
|
||||
|
||||
THREE.Curve.prototype.getTangentAt = function ( u ) {
|
||||
|
||||
var t = this.getUtoTmapping( u );
|
||||
return this.getTangent( t );
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************************
|
||||
* Utils
|
||||
**************************************************************/
|
||||
|
||||
THREE.Curve.utils = {
|
||||
|
||||
tangentQuadraticBezier: function ( t, p0, p1, p2 ) {
|
||||
|
||||
return 2 * ( 1 - t ) * ( p1 - p0 ) + 2 * t * ( p2 - p1 );
|
||||
|
||||
},
|
||||
|
||||
// Puay Bing, thanks for helping with this derivative!
|
||||
|
||||
tangentCubicBezier: function (t, p0, p1, p2, p3 ) {
|
||||
|
||||
return - 3 * p0 * (1 - t) * (1 - t) +
|
||||
3 * p1 * (1 - t) * (1-t) - 6 *t *p1 * (1-t) +
|
||||
6 * t * p2 * (1-t) - 3 * t * t * p2 +
|
||||
3 * t * t * p3;
|
||||
},
|
||||
|
||||
|
||||
tangentSpline: function ( t, p0, p1, p2, p3 ) {
|
||||
|
||||
// To check if my formulas are correct
|
||||
|
||||
var h00 = 6 * t * t - 6 * t; // derived from 2t^3 − 3t^2 + 1
|
||||
var h10 = 3 * t * t - 4 * t + 1; // t^3 − 2t^2 + t
|
||||
var h01 = - 6 * t * t + 6 * t; // − 2t3 + 3t2
|
||||
var h11 = 3 * t * t - 2 * t; // t3 − t2
|
||||
|
||||
return h00 + h10 + h01 + h11;
|
||||
|
||||
},
|
||||
|
||||
// Catmull-Rom
|
||||
|
||||
interpolate: function( p0, p1, p2, p3, t ) {
|
||||
|
||||
var v0 = ( p2 - p0 ) * 0.5;
|
||||
var v1 = ( p3 - p1 ) * 0.5;
|
||||
var t2 = t * t;
|
||||
var t3 = t * t2;
|
||||
return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// TODO: Transformation for Curves?
|
||||
|
||||
/**************************************************************
|
||||
* 3D Curves
|
||||
**************************************************************/
|
||||
|
||||
// A Factory method for creating new curve subclasses
|
||||
|
||||
THREE.Curve.create = function ( constructor, getPointFunc ) {
|
||||
|
||||
constructor.prototype = Object.create( THREE.Curve.prototype );
|
||||
constructor.prototype.getPoint = getPointFunc;
|
||||
|
||||
return constructor;
|
||||
|
||||
};
|
||||
|
|
@ -1,325 +0,0 @@
|
|||
/**
|
||||
* @author zz85 / http://www.lab4games.net/zz85/blog
|
||||
*
|
||||
**/
|
||||
|
||||
/**************************************************************
|
||||
* Curved Path - a curve path is simply a array of connected
|
||||
* curves, but retains the api of a curve
|
||||
**************************************************************/
|
||||
|
||||
THREE.CurvePath = function () {
|
||||
|
||||
this.curves = [];
|
||||
this.bends = [];
|
||||
|
||||
this.autoClose = false; // Automatically closes the path
|
||||
};
|
||||
|
||||
THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype );
|
||||
|
||||
THREE.CurvePath.prototype.add = function ( curve ) {
|
||||
|
||||
this.curves.push( curve );
|
||||
|
||||
};
|
||||
|
||||
THREE.CurvePath.prototype.checkConnection = function() {
|
||||
// TODO
|
||||
// If the ending of curve is not connected to the starting
|
||||
// or the next curve, then, this is not a real path
|
||||
};
|
||||
|
||||
THREE.CurvePath.prototype.closePath = function() {
|
||||
// TODO Test
|
||||
// and verify for vector3 (needs to implement equals)
|
||||
// Add a line curve if start and end of lines are not connected
|
||||
var startPoint = this.curves[0].getPoint(0);
|
||||
var endPoint = this.curves[this.curves.length-1].getPoint(1);
|
||||
|
||||
if (! startPoint.equals(endPoint)) {
|
||||
this.curves.push( new THREE.LineCurve(endPoint, startPoint) );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// To get accurate point with reference to
|
||||
// entire path distance at time t,
|
||||
// following has to be done:
|
||||
|
||||
// 1. Length of each sub path have to be known
|
||||
// 2. Locate and identify type of curve
|
||||
// 3. Get t for the curve
|
||||
// 4. Return curve.getPointAt(t')
|
||||
|
||||
THREE.CurvePath.prototype.getPoint = function( t ) {
|
||||
|
||||
var d = t * this.getLength();
|
||||
var curveLengths = this.getCurveLengths();
|
||||
var i = 0, diff, curve;
|
||||
|
||||
// To think about boundaries points.
|
||||
|
||||
while ( i < curveLengths.length ) {
|
||||
|
||||
if ( curveLengths[ i ] >= d ) {
|
||||
|
||||
diff = curveLengths[ i ] - d;
|
||||
curve = this.curves[ i ];
|
||||
|
||||
var u = 1 - diff / curve.getLength();
|
||||
|
||||
return curve.getPointAt( u );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
i ++;
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
// loop where sum != 0, sum > d , sum+1 <d
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
THREE.CurvePath.prototype.getTangent = function( t ) {
|
||||
};*/
|
||||
|
||||
|
||||
// We cannot use the default THREE.Curve getPoint() with getLength() because in
|
||||
// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
|
||||
// getPoint() depends on getLength
|
||||
|
||||
THREE.CurvePath.prototype.getLength = function() {
|
||||
|
||||
var lens = this.getCurveLengths();
|
||||
return lens[ lens.length - 1 ];
|
||||
|
||||
};
|
||||
|
||||
// Compute lengths and cache them
|
||||
// We cannot overwrite getLengths() because UtoT mapping uses it.
|
||||
|
||||
THREE.CurvePath.prototype.getCurveLengths = function() {
|
||||
|
||||
// We use cache values if curves and cache array are same length
|
||||
|
||||
if ( this.cacheLengths && this.cacheLengths.length == this.curves.length ) {
|
||||
|
||||
return this.cacheLengths;
|
||||
|
||||
};
|
||||
|
||||
// Get length of subsurve
|
||||
// Push sums into cached array
|
||||
|
||||
var lengths = [], sums = 0;
|
||||
var i, il = this.curves.length;
|
||||
|
||||
for ( i = 0; i < il; i ++ ) {
|
||||
|
||||
sums += this.curves[ i ].getLength();
|
||||
lengths.push( sums );
|
||||
|
||||
}
|
||||
|
||||
this.cacheLengths = lengths;
|
||||
|
||||
return lengths;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Returns min and max coordinates
|
||||
|
||||
THREE.CurvePath.prototype.getBoundingBox = function () {
|
||||
|
||||
var points = this.getPoints();
|
||||
|
||||
var maxX, maxY, maxZ;
|
||||
var minX, minY, minZ;
|
||||
|
||||
maxX = maxY = Number.NEGATIVE_INFINITY;
|
||||
minX = minY = Number.POSITIVE_INFINITY;
|
||||
|
||||
var p, i, il, sum;
|
||||
|
||||
var v3 = points[0] instanceof THREE.Vector3;
|
||||
|
||||
sum = v3 ? new THREE.Vector3() : new THREE.Vector2();
|
||||
|
||||
for ( i = 0, il = points.length; i < il; i ++ ) {
|
||||
|
||||
p = points[ i ];
|
||||
|
||||
if ( p.x > maxX ) maxX = p.x;
|
||||
else if ( p.x < minX ) minX = p.x;
|
||||
|
||||
if ( p.y > maxY ) maxY = p.y;
|
||||
else if ( p.y < minY ) minY = p.y;
|
||||
|
||||
if ( v3 ) {
|
||||
|
||||
if ( p.z > maxZ ) maxZ = p.z;
|
||||
else if ( p.z < minZ ) minZ = p.z;
|
||||
|
||||
}
|
||||
|
||||
sum.add( p );
|
||||
|
||||
}
|
||||
|
||||
var ret = {
|
||||
|
||||
minX: minX,
|
||||
minY: minY,
|
||||
maxX: maxX,
|
||||
maxY: maxY
|
||||
|
||||
};
|
||||
|
||||
if ( v3 ) {
|
||||
|
||||
ret.maxZ = maxZ;
|
||||
ret.minZ = minZ;
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
};
|
||||
|
||||
/**************************************************************
|
||||
* Create Geometries Helpers
|
||||
**************************************************************/
|
||||
|
||||
/// Generate geometry from path points (for Line or Points objects)
|
||||
|
||||
THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
|
||||
|
||||
var pts = this.getPoints( divisions, true );
|
||||
return this.createGeometry( pts );
|
||||
|
||||
};
|
||||
|
||||
// Generate geometry from equidistance sampling along the path
|
||||
|
||||
THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
|
||||
|
||||
var pts = this.getSpacedPoints( divisions, true );
|
||||
return this.createGeometry( pts );
|
||||
|
||||
};
|
||||
|
||||
THREE.CurvePath.prototype.createGeometry = function( points ) {
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
for ( var i = 0; i < points.length; i ++ ) {
|
||||
|
||||
geometry.vertices.push( new THREE.Vector3( points[ i ].x, points[ i ].y, points[ i ].z || 0) );
|
||||
|
||||
}
|
||||
|
||||
return geometry;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************
|
||||
* Bend / Wrap Helper Methods
|
||||
**************************************************************/
|
||||
|
||||
// Wrap path / Bend modifiers?
|
||||
|
||||
THREE.CurvePath.prototype.addWrapPath = function ( bendpath ) {
|
||||
|
||||
this.bends.push( bendpath );
|
||||
|
||||
};
|
||||
|
||||
THREE.CurvePath.prototype.getTransformedPoints = function( segments, bends ) {
|
||||
|
||||
var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints
|
||||
var i, il;
|
||||
|
||||
if ( ! bends ) {
|
||||
|
||||
bends = this.bends;
|
||||
|
||||
}
|
||||
|
||||
for ( i = 0, il = bends.length; i < il; i ++ ) {
|
||||
|
||||
oldPts = this.getWrapPoints( oldPts, bends[ i ] );
|
||||
|
||||
}
|
||||
|
||||
return oldPts;
|
||||
|
||||
};
|
||||
|
||||
THREE.CurvePath.prototype.getTransformedSpacedPoints = function( segments, bends ) {
|
||||
|
||||
var oldPts = this.getSpacedPoints( segments );
|
||||
|
||||
var i, il;
|
||||
|
||||
if ( ! bends ) {
|
||||
|
||||
bends = this.bends;
|
||||
|
||||
}
|
||||
|
||||
for ( i = 0, il = bends.length; i < il; i ++ ) {
|
||||
|
||||
oldPts = this.getWrapPoints( oldPts, bends[ i ] );
|
||||
|
||||
}
|
||||
|
||||
return oldPts;
|
||||
|
||||
};
|
||||
|
||||
// This returns getPoints() bend/wrapped around the contour of a path.
|
||||
// Read http://www.planetclegg.com/projects/WarpingTextToSplines.html
|
||||
|
||||
THREE.CurvePath.prototype.getWrapPoints = function ( oldPts, path ) {
|
||||
|
||||
var bounds = this.getBoundingBox();
|
||||
|
||||
var i, il, p, oldX, oldY, xNorm;
|
||||
|
||||
for ( i = 0, il = oldPts.length; i < il; i ++ ) {
|
||||
|
||||
p = oldPts[ i ];
|
||||
|
||||
oldX = p.x;
|
||||
oldY = p.y;
|
||||
|
||||
xNorm = oldX / bounds.maxX;
|
||||
|
||||
// If using actual distance, for length > path, requires line extrusions
|
||||
//xNorm = path.getUtoTmapping(xNorm, oldX); // 3 styles. 1) wrap stretched. 2) wrap stretch by arc length 3) warp by actual distance
|
||||
|
||||
xNorm = path.getUtoTmapping( xNorm, oldX );
|
||||
|
||||
// check for out of bounds?
|
||||
|
||||
var pathPt = path.getPoint( xNorm );
|
||||
var normal = path.getTangent( xNorm );
|
||||
normal.set( - normal.y, normal.x ).multiplyScalar( oldY );
|
||||
|
||||
p.x = pathPt.x + normal.x;
|
||||
p.y = pathPt.y + normal.y;
|
||||
|
||||
}
|
||||
|
||||
return oldPts;
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.Gyroscope = function () {
|
||||
|
||||
THREE.Object3D.call( this );
|
||||
|
||||
};
|
||||
|
||||
THREE.Gyroscope.prototype = Object.create( THREE.Object3D.prototype );
|
||||
|
||||
THREE.Gyroscope.prototype.updateMatrixWorld = function ( force ) {
|
||||
|
||||
this.matrixAutoUpdate && this.updateMatrix();
|
||||
|
||||
// update matrixWorld
|
||||
|
||||
if ( this.matrixWorldNeedsUpdate || force ) {
|
||||
|
||||
if ( this.parent ) {
|
||||
|
||||
this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
|
||||
|
||||
this.matrixWorld.decompose( this.translationWorld, this.quaternionWorld, this.scaleWorld );
|
||||
this.matrix.decompose( this.translationObject, this.quaternionObject, this.scaleObject );
|
||||
|
||||
this.matrixWorld.compose( this.translationWorld, this.quaternionObject, this.scaleWorld );
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
this.matrixWorld.copy( this.matrix );
|
||||
|
||||
}
|
||||
|
||||
|
||||
this.matrixWorldNeedsUpdate = false;
|
||||
|
||||
force = true;
|
||||
|
||||
}
|
||||
|
||||
// update children
|
||||
|
||||
for ( var i = 0, l = this.children.length; i < l; i ++ ) {
|
||||
|
||||
this.children[ i ].updateMatrixWorld( force );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.Gyroscope.prototype.translationWorld = new THREE.Vector3();
|
||||
THREE.Gyroscope.prototype.translationObject = new THREE.Vector3();
|
||||
THREE.Gyroscope.prototype.quaternionWorld = new THREE.Quaternion();
|
||||
THREE.Gyroscope.prototype.quaternionObject = new THREE.Quaternion();
|
||||
THREE.Gyroscope.prototype.scaleWorld = new THREE.Vector3();
|
||||
THREE.Gyroscope.prototype.scaleObject = new THREE.Vector3();
|
||||
|
||||
|
|
@ -1,675 +0,0 @@
|
|||
/**
|
||||
* @author zz85 / http://www.lab4games.net/zz85/blog
|
||||
* Creates free form 2d path using series of points, lines or curves.
|
||||
*
|
||||
**/
|
||||
|
||||
THREE.Path = function ( points ) {
|
||||
|
||||
THREE.CurvePath.call(this);
|
||||
|
||||
this.actions = [];
|
||||
|
||||
if ( points ) {
|
||||
|
||||
this.fromPoints( points );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.Path.prototype = Object.create( THREE.CurvePath.prototype );
|
||||
|
||||
THREE.PathActions = {
|
||||
|
||||
MOVE_TO: 'moveTo',
|
||||
LINE_TO: 'lineTo',
|
||||
QUADRATIC_CURVE_TO: 'quadraticCurveTo', // Bezier quadratic curve
|
||||
BEZIER_CURVE_TO: 'bezierCurveTo', // Bezier cubic curve
|
||||
CSPLINE_THRU: 'splineThru', // Catmull-rom spline
|
||||
ARC: 'arc', // Circle
|
||||
ELLIPSE: 'ellipse'
|
||||
};
|
||||
|
||||
// TODO Clean up PATH API
|
||||
|
||||
// Create path using straight lines to connect all points
|
||||
// - vectors: array of Vector2
|
||||
|
||||
THREE.Path.prototype.fromPoints = function ( vectors ) {
|
||||
|
||||
this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
|
||||
|
||||
for ( var v = 1, vlen = vectors.length; v < vlen; v ++ ) {
|
||||
|
||||
this.lineTo( vectors[ v ].x, vectors[ v ].y );
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// startPath() endPath()?
|
||||
|
||||
THREE.Path.prototype.moveTo = function ( x, y ) {
|
||||
|
||||
var args = Array.prototype.slice.call( arguments );
|
||||
this.actions.push( { action: THREE.PathActions.MOVE_TO, args: args } );
|
||||
|
||||
};
|
||||
|
||||
THREE.Path.prototype.lineTo = function ( x, y ) {
|
||||
|
||||
var args = Array.prototype.slice.call( arguments );
|
||||
|
||||
var lastargs = this.actions[ this.actions.length - 1 ].args;
|
||||
|
||||
var x0 = lastargs[ lastargs.length - 2 ];
|
||||
var y0 = lastargs[ lastargs.length - 1 ];
|
||||
|
||||
var curve = new THREE.LineCurve( new THREE.Vector2( x0, y0 ), new THREE.Vector2( x, y ) );
|
||||
this.curves.push( curve );
|
||||
|
||||
this.actions.push( { action: THREE.PathActions.LINE_TO, args: args } );
|
||||
|
||||
};
|
||||
|
||||
THREE.Path.prototype.quadraticCurveTo = function( aCPx, aCPy, aX, aY ) {
|
||||
|
||||
var args = Array.prototype.slice.call( arguments );
|
||||
|
||||
var lastargs = this.actions[ this.actions.length - 1 ].args;
|
||||
|
||||
var x0 = lastargs[ lastargs.length - 2 ];
|
||||
var y0 = lastargs[ lastargs.length - 1 ];
|
||||
|
||||
var curve = new THREE.QuadraticBezierCurve( new THREE.Vector2( x0, y0 ),
|
||||
new THREE.Vector2( aCPx, aCPy ),
|
||||
new THREE.Vector2( aX, aY ) );
|
||||
this.curves.push( curve );
|
||||
|
||||
this.actions.push( { action: THREE.PathActions.QUADRATIC_CURVE_TO, args: args } );
|
||||
|
||||
};
|
||||
|
||||
THREE.Path.prototype.bezierCurveTo = function( aCP1x, aCP1y,
|
||||
aCP2x, aCP2y,
|
||||
aX, aY ) {
|
||||
|
||||
var args = Array.prototype.slice.call( arguments );
|
||||
|
||||
var lastargs = this.actions[ this.actions.length - 1 ].args;
|
||||
|
||||
var x0 = lastargs[ lastargs.length - 2 ];
|
||||
var y0 = lastargs[ lastargs.length - 1 ];
|
||||
|
||||
var curve = new THREE.CubicBezierCurve( new THREE.Vector2( x0, y0 ),
|
||||
new THREE.Vector2( aCP1x, aCP1y ),
|
||||
new THREE.Vector2( aCP2x, aCP2y ),
|
||||
new THREE.Vector2( aX, aY ) );
|
||||
this.curves.push( curve );
|
||||
|
||||
this.actions.push( { action: THREE.PathActions.BEZIER_CURVE_TO, args: args } );
|
||||
|
||||
};
|
||||
|
||||
THREE.Path.prototype.splineThru = function( pts /*Array of Vector*/ ) {
|
||||
|
||||
var args = Array.prototype.slice.call( arguments );
|
||||
var lastargs = this.actions[ this.actions.length - 1 ].args;
|
||||
|
||||
var x0 = lastargs[ lastargs.length - 2 ];
|
||||
var y0 = lastargs[ lastargs.length - 1 ];
|
||||
//---
|
||||
var npts = [ new THREE.Vector2( x0, y0 ) ];
|
||||
Array.prototype.push.apply( npts, pts );
|
||||
|
||||
var curve = new THREE.SplineCurve( npts );
|
||||
this.curves.push( curve );
|
||||
|
||||
this.actions.push( { action: THREE.PathActions.CSPLINE_THRU, args: args } );
|
||||
|
||||
};
|
||||
|
||||
// FUTURE: Change the API or follow canvas API?
|
||||
|
||||
THREE.Path.prototype.arc = function ( aX, aY, aRadius,
|
||||
aStartAngle, aEndAngle, aClockwise ) {
|
||||
|
||||
var lastargs = this.actions[ this.actions.length - 1].args;
|
||||
var x0 = lastargs[ lastargs.length - 2 ];
|
||||
var y0 = lastargs[ lastargs.length - 1 ];
|
||||
|
||||
this.absarc(aX + x0, aY + y0, aRadius,
|
||||
aStartAngle, aEndAngle, aClockwise );
|
||||
|
||||
};
|
||||
|
||||
THREE.Path.prototype.absarc = function ( aX, aY, aRadius,
|
||||
aStartAngle, aEndAngle, aClockwise ) {
|
||||
this.absellipse(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
|
||||
};
|
||||
|
||||
THREE.Path.prototype.ellipse = function ( aX, aY, xRadius, yRadius,
|
||||
aStartAngle, aEndAngle, aClockwise ) {
|
||||
|
||||
var lastargs = this.actions[ this.actions.length - 1].args;
|
||||
var x0 = lastargs[ lastargs.length - 2 ];
|
||||
var y0 = lastargs[ lastargs.length - 1 ];
|
||||
|
||||
this.absellipse(aX + x0, aY + y0, xRadius, yRadius,
|
||||
aStartAngle, aEndAngle, aClockwise );
|
||||
|
||||
};
|
||||
|
||||
|
||||
THREE.Path.prototype.absellipse = function ( aX, aY, xRadius, yRadius,
|
||||
aStartAngle, aEndAngle, aClockwise ) {
|
||||
|
||||
var args = Array.prototype.slice.call( arguments );
|
||||
var curve = new THREE.EllipseCurve( aX, aY, xRadius, yRadius,
|
||||
aStartAngle, aEndAngle, aClockwise );
|
||||
this.curves.push( curve );
|
||||
|
||||
var lastPoint = curve.getPoint(1);
|
||||
args.push(lastPoint.x);
|
||||
args.push(lastPoint.y);
|
||||
|
||||
this.actions.push( { action: THREE.PathActions.ELLIPSE, args: args } );
|
||||
|
||||
};
|
||||
|
||||
THREE.Path.prototype.getSpacedPoints = function ( divisions, closedPath ) {
|
||||
|
||||
if ( ! divisions ) divisions = 40;
|
||||
|
||||
var points = [];
|
||||
|
||||
for ( var i = 0; i < divisions; i ++ ) {
|
||||
|
||||
points.push( this.getPoint( i / divisions ) );
|
||||
|
||||
//if( !this.getPoint( i / divisions ) ) throw "DIE";
|
||||
|
||||
}
|
||||
|
||||
// if ( closedPath ) {
|
||||
//
|
||||
// points.push( points[ 0 ] );
|
||||
//
|
||||
// }
|
||||
|
||||
return points;
|
||||
|
||||
};
|
||||
|
||||
/* Return an array of vectors based on contour of the path */
|
||||
|
||||
THREE.Path.prototype.getPoints = function( divisions, closedPath ) {
|
||||
|
||||
if (this.useSpacedPoints) {
|
||||
console.log('tata');
|
||||
return this.getSpacedPoints( divisions, closedPath );
|
||||
}
|
||||
|
||||
divisions = divisions || 12;
|
||||
|
||||
var points = [];
|
||||
|
||||
var i, il, item, action, args;
|
||||
var cpx, cpy, cpx2, cpy2, cpx1, cpy1, cpx0, cpy0,
|
||||
laste, j,
|
||||
t, tx, ty;
|
||||
|
||||
for ( i = 0, il = this.actions.length; i < il; i ++ ) {
|
||||
|
||||
item = this.actions[ i ];
|
||||
|
||||
action = item.action;
|
||||
args = item.args;
|
||||
|
||||
switch( action ) {
|
||||
|
||||
case THREE.PathActions.MOVE_TO:
|
||||
|
||||
points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
|
||||
|
||||
break;
|
||||
|
||||
case THREE.PathActions.LINE_TO:
|
||||
|
||||
points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
|
||||
|
||||
break;
|
||||
|
||||
case THREE.PathActions.QUADRATIC_CURVE_TO:
|
||||
|
||||
cpx = args[ 2 ];
|
||||
cpy = args[ 3 ];
|
||||
|
||||
cpx1 = args[ 0 ];
|
||||
cpy1 = args[ 1 ];
|
||||
|
||||
if ( points.length > 0 ) {
|
||||
|
||||
laste = points[ points.length - 1 ];
|
||||
|
||||
cpx0 = laste.x;
|
||||
cpy0 = laste.y;
|
||||
|
||||
} else {
|
||||
|
||||
laste = this.actions[ i - 1 ].args;
|
||||
|
||||
cpx0 = laste[ laste.length - 2 ];
|
||||
cpy0 = laste[ laste.length - 1 ];
|
||||
|
||||
}
|
||||
|
||||
for ( j = 1; j <= divisions; j ++ ) {
|
||||
|
||||
t = j / divisions;
|
||||
|
||||
tx = THREE.Shape.utils.b2( t, cpx0, cpx1, cpx );
|
||||
ty = THREE.Shape.utils.b2( t, cpy0, cpy1, cpy );
|
||||
|
||||
points.push( new THREE.Vector2( tx, ty ) );
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case THREE.PathActions.BEZIER_CURVE_TO:
|
||||
|
||||
cpx = args[ 4 ];
|
||||
cpy = args[ 5 ];
|
||||
|
||||
cpx1 = args[ 0 ];
|
||||
cpy1 = args[ 1 ];
|
||||
|
||||
cpx2 = args[ 2 ];
|
||||
cpy2 = args[ 3 ];
|
||||
|
||||
if ( points.length > 0 ) {
|
||||
|
||||
laste = points[ points.length - 1 ];
|
||||
|
||||
cpx0 = laste.x;
|
||||
cpy0 = laste.y;
|
||||
|
||||
} else {
|
||||
|
||||
laste = this.actions[ i - 1 ].args;
|
||||
|
||||
cpx0 = laste[ laste.length - 2 ];
|
||||
cpy0 = laste[ laste.length - 1 ];
|
||||
|
||||
}
|
||||
|
||||
|
||||
for ( j = 1; j <= divisions; j ++ ) {
|
||||
|
||||
t = j / divisions;
|
||||
|
||||
tx = THREE.Shape.utils.b3( t, cpx0, cpx1, cpx2, cpx );
|
||||
ty = THREE.Shape.utils.b3( t, cpy0, cpy1, cpy2, cpy );
|
||||
|
||||
points.push( new THREE.Vector2( tx, ty ) );
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case THREE.PathActions.CSPLINE_THRU:
|
||||
|
||||
laste = this.actions[ i - 1 ].args;
|
||||
|
||||
var last = new THREE.Vector2( laste[ laste.length - 2 ], laste[ laste.length - 1 ] );
|
||||
var spts = [ last ];
|
||||
|
||||
var n = divisions * args[ 0 ].length;
|
||||
|
||||
spts = spts.concat( args[ 0 ] );
|
||||
|
||||
var spline = new THREE.SplineCurve( spts );
|
||||
|
||||
for ( j = 1; j <= n; j ++ ) {
|
||||
|
||||
points.push( spline.getPointAt( j / n ) ) ;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case THREE.PathActions.ARC:
|
||||
|
||||
var aX = args[ 0 ], aY = args[ 1 ],
|
||||
aRadius = args[ 2 ],
|
||||
aStartAngle = args[ 3 ], aEndAngle = args[ 4 ],
|
||||
aClockwise = !! args[ 5 ];
|
||||
|
||||
var deltaAngle = aEndAngle - aStartAngle;
|
||||
var angle;
|
||||
var tdivisions = divisions * 2;
|
||||
|
||||
for ( j = 1; j <= tdivisions; j ++ ) {
|
||||
|
||||
t = j / tdivisions;
|
||||
|
||||
if ( ! aClockwise ) {
|
||||
|
||||
t = 1 - t;
|
||||
|
||||
}
|
||||
|
||||
angle = aStartAngle + t * deltaAngle;
|
||||
|
||||
tx = aX + aRadius * Math.cos( angle );
|
||||
ty = aY + aRadius * Math.sin( angle );
|
||||
|
||||
//console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
|
||||
|
||||
points.push( new THREE.Vector2( tx, ty ) );
|
||||
|
||||
}
|
||||
|
||||
//console.log(points);
|
||||
|
||||
break;
|
||||
|
||||
case THREE.PathActions.ELLIPSE:
|
||||
|
||||
var aX = args[ 0 ], aY = args[ 1 ],
|
||||
xRadius = args[ 2 ],
|
||||
yRadius = args[ 3 ],
|
||||
aStartAngle = args[ 4 ], aEndAngle = args[ 5 ],
|
||||
aClockwise = !! args[ 6 ];
|
||||
|
||||
|
||||
var deltaAngle = aEndAngle - aStartAngle;
|
||||
var angle;
|
||||
var tdivisions = divisions * 2;
|
||||
|
||||
for ( j = 1; j <= tdivisions; j ++ ) {
|
||||
|
||||
t = j / tdivisions;
|
||||
|
||||
if ( ! aClockwise ) {
|
||||
|
||||
t = 1 - t;
|
||||
|
||||
}
|
||||
|
||||
angle = aStartAngle + t * deltaAngle;
|
||||
|
||||
tx = aX + xRadius * Math.cos( angle );
|
||||
ty = aY + yRadius * Math.sin( angle );
|
||||
|
||||
//console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
|
||||
|
||||
points.push( new THREE.Vector2( tx, ty ) );
|
||||
|
||||
}
|
||||
|
||||
//console.log(points);
|
||||
|
||||
break;
|
||||
|
||||
} // end switch
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Normalize to remove the closing point by default.
|
||||
var lastPoint = points[ points.length - 1];
|
||||
var EPSILON = 0.0000000001;
|
||||
if ( Math.abs(lastPoint.x - points[ 0 ].x) < EPSILON &&
|
||||
Math.abs(lastPoint.y - points[ 0 ].y) < EPSILON)
|
||||
points.splice( points.length - 1, 1);
|
||||
if ( closedPath ) {
|
||||
|
||||
points.push( points[ 0 ] );
|
||||
|
||||
}
|
||||
|
||||
return points;
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
// Breaks path into shapes
|
||||
//
|
||||
// Assumptions (if parameter isCCW==true the opposite holds):
|
||||
// - solid shapes are defined clockwise (CW)
|
||||
// - holes are defined counterclockwise (CCW)
|
||||
//
|
||||
// If parameter noHoles==true:
|
||||
// - all subPaths are regarded as solid shapes
|
||||
// - definition order CW/CCW has no relevance
|
||||
//
|
||||
|
||||
THREE.Path.prototype.toShapes = function( isCCW, noHoles ) {
|
||||
|
||||
function extractSubpaths( inActions ) {
|
||||
|
||||
var i, il, item, action, args;
|
||||
|
||||
var subPaths = [], lastPath = new THREE.Path();
|
||||
|
||||
for ( i = 0, il = inActions.length; i < il; i ++ ) {
|
||||
|
||||
item = inActions[ i ];
|
||||
|
||||
args = item.args;
|
||||
action = item.action;
|
||||
|
||||
if ( action == THREE.PathActions.MOVE_TO ) {
|
||||
|
||||
if ( lastPath.actions.length != 0 ) {
|
||||
|
||||
subPaths.push( lastPath );
|
||||
lastPath = new THREE.Path();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lastPath[ action ].apply( lastPath, args );
|
||||
|
||||
}
|
||||
|
||||
if ( lastPath.actions.length != 0 ) {
|
||||
|
||||
subPaths.push( lastPath );
|
||||
|
||||
}
|
||||
|
||||
// console.log(subPaths);
|
||||
|
||||
return subPaths;
|
||||
}
|
||||
|
||||
function toShapesNoHoles( inSubpaths ) {
|
||||
|
||||
var shapes = [];
|
||||
|
||||
for ( var i = 0, il = inSubpaths.length; i < il; i ++ ) {
|
||||
|
||||
var tmpPath = inSubpaths[ i ];
|
||||
|
||||
var tmpShape = new THREE.Shape();
|
||||
tmpShape.actions = tmpPath.actions;
|
||||
tmpShape.curves = tmpPath.curves;
|
||||
|
||||
shapes.push( tmpShape );
|
||||
}
|
||||
|
||||
//console.log("shape", shapes);
|
||||
|
||||
return shapes;
|
||||
};
|
||||
|
||||
function isPointInsidePolygon( inPt, inPolygon ) {
|
||||
var EPSILON = 0.0000000001;
|
||||
|
||||
var polyLen = inPolygon.length;
|
||||
|
||||
// inPt on polygon contour => immediate success or
|
||||
// toggling of inside/outside at every single! intersection point of an edge
|
||||
// with the horizontal line through inPt, left of inPt
|
||||
// not counting lowerY endpoints of edges and whole edges on that line
|
||||
var inside = false;
|
||||
for( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
|
||||
var edgeLowPt = inPolygon[ p ];
|
||||
var edgeHighPt = inPolygon[ q ];
|
||||
|
||||
var edgeDx = edgeHighPt.x - edgeLowPt.x;
|
||||
var edgeDy = edgeHighPt.y - edgeLowPt.y;
|
||||
|
||||
if ( Math.abs(edgeDy) > EPSILON ) { // not parallel
|
||||
if ( edgeDy < 0 ) {
|
||||
edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
|
||||
edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
|
||||
}
|
||||
if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue;
|
||||
|
||||
if ( inPt.y == edgeLowPt.y ) {
|
||||
if ( inPt.x == edgeLowPt.x ) return true; // inPt is on contour ?
|
||||
// continue; // no intersection or edgeLowPt => doesn't count !!!
|
||||
} else {
|
||||
var perpEdge = edgeDy * (inPt.x - edgeLowPt.x) - edgeDx * (inPt.y - edgeLowPt.y);
|
||||
if ( perpEdge == 0 ) return true; // inPt is on contour ?
|
||||
if ( perpEdge < 0 ) continue;
|
||||
inside = ! inside; // true intersection left of inPt
|
||||
}
|
||||
} else { // parallel or colinear
|
||||
if ( inPt.y != edgeLowPt.y ) continue; // parallel
|
||||
// egde lies on the same horizontal line as inPt
|
||||
if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
|
||||
( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour !
|
||||
// continue;
|
||||
}
|
||||
}
|
||||
|
||||
return inside;
|
||||
}
|
||||
|
||||
|
||||
var subPaths = extractSubpaths( this.actions );
|
||||
if ( subPaths.length == 0 ) return [];
|
||||
|
||||
if ( noHoles === true ) return toShapesNoHoles( subPaths );
|
||||
|
||||
|
||||
var solid, tmpPath, tmpShape, shapes = [];
|
||||
|
||||
if ( subPaths.length == 1) {
|
||||
|
||||
tmpPath = subPaths[0];
|
||||
tmpShape = new THREE.Shape();
|
||||
tmpShape.actions = tmpPath.actions;
|
||||
tmpShape.curves = tmpPath.curves;
|
||||
shapes.push( tmpShape );
|
||||
return shapes;
|
||||
|
||||
}
|
||||
|
||||
var holesFirst = ! THREE.Shape.utils.isClockWise( subPaths[ 0 ].getPoints() );
|
||||
holesFirst = isCCW ? ! holesFirst : holesFirst;
|
||||
|
||||
// console.log("Holes first", holesFirst);
|
||||
|
||||
var betterShapeHoles = [];
|
||||
var newShapes = [];
|
||||
var newShapeHoles = [];
|
||||
var mainIdx = 0;
|
||||
var tmpPoints;
|
||||
|
||||
newShapes[mainIdx] = undefined;
|
||||
newShapeHoles[mainIdx] = [];
|
||||
|
||||
var i, il;
|
||||
|
||||
for ( i = 0, il = subPaths.length; i < il; i ++ ) {
|
||||
|
||||
tmpPath = subPaths[ i ];
|
||||
tmpPoints = tmpPath.getPoints();
|
||||
solid = THREE.Shape.utils.isClockWise( tmpPoints );
|
||||
solid = isCCW ? ! solid : solid;
|
||||
|
||||
if ( solid ) {
|
||||
|
||||
if ( (! holesFirst ) && ( newShapes[mainIdx] ) ) mainIdx ++;
|
||||
|
||||
newShapes[mainIdx] = { s: new THREE.Shape(), p: tmpPoints };
|
||||
newShapes[mainIdx].s.actions = tmpPath.actions;
|
||||
newShapes[mainIdx].s.curves = tmpPath.curves;
|
||||
|
||||
if ( holesFirst ) mainIdx ++;
|
||||
newShapeHoles[mainIdx] = [];
|
||||
|
||||
//console.log('cw', i);
|
||||
|
||||
} else {
|
||||
|
||||
newShapeHoles[mainIdx].push( { h: tmpPath, p: tmpPoints[0] } );
|
||||
|
||||
//console.log('ccw', i);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// only Holes? -> probably all Shapes with wrong orientation
|
||||
if ( ! newShapes[0] ) return toShapesNoHoles( subPaths );
|
||||
|
||||
|
||||
if ( newShapes.length > 1 ) {
|
||||
var ambigious = false;
|
||||
var toChange = [];
|
||||
|
||||
for (var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
|
||||
betterShapeHoles[sIdx] = [];
|
||||
}
|
||||
for (var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
|
||||
var sh = newShapes[sIdx];
|
||||
var sho = newShapeHoles[sIdx];
|
||||
for (var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
|
||||
var ho = sho[hIdx];
|
||||
var hole_unassigned = true;
|
||||
for (var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
|
||||
if ( isPointInsidePolygon( ho.p, newShapes[s2Idx].p ) ) {
|
||||
if ( sIdx != s2Idx ) toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
|
||||
if ( hole_unassigned ) {
|
||||
hole_unassigned = false;
|
||||
betterShapeHoles[s2Idx].push( ho );
|
||||
} else {
|
||||
ambigious = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( hole_unassigned ) { betterShapeHoles[sIdx].push( ho ); }
|
||||
}
|
||||
}
|
||||
// console.log("ambigious: ", ambigious);
|
||||
if ( toChange.length > 0 ) {
|
||||
// console.log("to change: ", toChange);
|
||||
if (! ambigious) newShapeHoles = betterShapeHoles;
|
||||
}
|
||||
}
|
||||
|
||||
var tmpHoles, j, jl;
|
||||
for ( i = 0, il = newShapes.length; i < il; i ++ ) {
|
||||
tmpShape = newShapes[i].s;
|
||||
shapes.push( tmpShape );
|
||||
tmpHoles = newShapeHoles[i];
|
||||
for ( j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
|
||||
tmpShape.holes.push( tmpHoles[j].h );
|
||||
}
|
||||
}
|
||||
|
||||
//console.log("shape", shapes);
|
||||
|
||||
return shapes;
|
||||
|
||||
};
|
||||
|
|
@ -1,576 +0,0 @@
|
|||
/**
|
||||
* @author zz85 / http://www.lab4games.net/zz85/blog
|
||||
* Defines a 2d shape plane using paths.
|
||||
**/
|
||||
|
||||
// STEP 1 Create a path.
|
||||
// STEP 2 Turn path into shape.
|
||||
// STEP 3 ExtrudeGeometry takes in Shape/Shapes
|
||||
// STEP 3a - Extract points from each shape, turn to vertices
|
||||
// STEP 3b - Triangulate each shape, add faces.
|
||||
|
||||
THREE.Shape = function () {
|
||||
|
||||
THREE.Path.apply( this, arguments );
|
||||
this.holes = [];
|
||||
|
||||
};
|
||||
|
||||
THREE.Shape.prototype = Object.create( THREE.Path.prototype );
|
||||
|
||||
// Convenience method to return ExtrudeGeometry
|
||||
|
||||
THREE.Shape.prototype.extrude = function ( options ) {
|
||||
|
||||
var extruded = new THREE.ExtrudeGeometry( this, options );
|
||||
return extruded;
|
||||
|
||||
};
|
||||
|
||||
// Convenience method to return ShapeGeometry
|
||||
|
||||
THREE.Shape.prototype.makeGeometry = function ( options ) {
|
||||
|
||||
var geometry = new THREE.ShapeGeometry( this, options );
|
||||
return geometry;
|
||||
|
||||
};
|
||||
|
||||
// Get points of holes
|
||||
|
||||
THREE.Shape.prototype.getPointsHoles = function ( divisions ) {
|
||||
|
||||
var i, il = this.holes.length, holesPts = [];
|
||||
|
||||
for ( i = 0; i < il; i ++ ) {
|
||||
|
||||
holesPts[ i ] = this.holes[ i ].getTransformedPoints( divisions, this.bends );
|
||||
|
||||
}
|
||||
|
||||
return holesPts;
|
||||
|
||||
};
|
||||
|
||||
// Get points of holes (spaced by regular distance)
|
||||
|
||||
THREE.Shape.prototype.getSpacedPointsHoles = function ( divisions ) {
|
||||
|
||||
var i, il = this.holes.length, holesPts = [];
|
||||
|
||||
for ( i = 0; i < il; i ++ ) {
|
||||
|
||||
holesPts[ i ] = this.holes[ i ].getTransformedSpacedPoints( divisions, this.bends );
|
||||
|
||||
}
|
||||
|
||||
return holesPts;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Get points of shape and holes (keypoints based on segments parameter)
|
||||
|
||||
THREE.Shape.prototype.extractAllPoints = function ( divisions ) {
|
||||
|
||||
return {
|
||||
|
||||
shape: this.getTransformedPoints( divisions ),
|
||||
holes: this.getPointsHoles( divisions )
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
THREE.Shape.prototype.extractPoints = function ( divisions ) {
|
||||
|
||||
if (this.useSpacedPoints) {
|
||||
return this.extractAllSpacedPoints(divisions);
|
||||
}
|
||||
|
||||
return this.extractAllPoints(divisions);
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
// THREE.Shape.prototype.extractAllPointsWithBend = function ( divisions, bend ) {
|
||||
//
|
||||
// return {
|
||||
//
|
||||
// shape: this.transform( bend, divisions ),
|
||||
// holes: this.getPointsHoles( divisions, bend )
|
||||
//
|
||||
// };
|
||||
//
|
||||
// };
|
||||
|
||||
// Get points of shape and holes (spaced by regular distance)
|
||||
|
||||
THREE.Shape.prototype.extractAllSpacedPoints = function ( divisions ) {
|
||||
|
||||
return {
|
||||
|
||||
shape: this.getTransformedSpacedPoints( divisions ),
|
||||
holes: this.getSpacedPointsHoles( divisions )
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/**************************************************************
|
||||
* Utils
|
||||
**************************************************************/
|
||||
|
||||
THREE.Shape.utils = {
|
||||
|
||||
triangulateShape: function ( contour, holes ) {
|
||||
|
||||
function point_in_segment_2D_colin( inSegPt1, inSegPt2, inOtherPt ) {
|
||||
// inOtherPt needs to be colinear to the inSegment
|
||||
if ( inSegPt1.x != inSegPt2.x ) {
|
||||
if ( inSegPt1.x < inSegPt2.x ) {
|
||||
return ( ( inSegPt1.x <= inOtherPt.x ) && ( inOtherPt.x <= inSegPt2.x ) );
|
||||
} else {
|
||||
return ( ( inSegPt2.x <= inOtherPt.x ) && ( inOtherPt.x <= inSegPt1.x ) );
|
||||
}
|
||||
} else {
|
||||
if ( inSegPt1.y < inSegPt2.y ) {
|
||||
return ( ( inSegPt1.y <= inOtherPt.y ) && ( inOtherPt.y <= inSegPt2.y ) );
|
||||
} else {
|
||||
return ( ( inSegPt2.y <= inOtherPt.y ) && ( inOtherPt.y <= inSegPt1.y ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function intersect_segments_2D( inSeg1Pt1, inSeg1Pt2, inSeg2Pt1, inSeg2Pt2, inExcludeAdjacentSegs ) {
|
||||
var EPSILON = 0.0000000001;
|
||||
|
||||
var seg1dx = inSeg1Pt2.x - inSeg1Pt1.x, seg1dy = inSeg1Pt2.y - inSeg1Pt1.y;
|
||||
var seg2dx = inSeg2Pt2.x - inSeg2Pt1.x, seg2dy = inSeg2Pt2.y - inSeg2Pt1.y;
|
||||
|
||||
var seg1seg2dx = inSeg1Pt1.x - inSeg2Pt1.x;
|
||||
var seg1seg2dy = inSeg1Pt1.y - inSeg2Pt1.y;
|
||||
|
||||
var limit = seg1dy * seg2dx - seg1dx * seg2dy;
|
||||
var perpSeg1 = seg1dy * seg1seg2dx - seg1dx * seg1seg2dy;
|
||||
|
||||
if ( Math.abs(limit) > EPSILON ) { // not parallel
|
||||
|
||||
var perpSeg2;
|
||||
if ( limit > 0 ) {
|
||||
if ( ( perpSeg1 < 0 ) || ( perpSeg1 > limit ) ) return [];
|
||||
perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy;
|
||||
if ( ( perpSeg2 < 0 ) || ( perpSeg2 > limit ) ) return [];
|
||||
} else {
|
||||
if ( ( perpSeg1 > 0 ) || ( perpSeg1 < limit ) ) return [];
|
||||
perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy;
|
||||
if ( ( perpSeg2 > 0 ) || ( perpSeg2 < limit ) ) return [];
|
||||
}
|
||||
|
||||
// i.e. to reduce rounding errors
|
||||
// intersection at endpoint of segment#1?
|
||||
if ( perpSeg2 == 0 ) {
|
||||
if ( ( inExcludeAdjacentSegs ) &&
|
||||
( ( perpSeg1 == 0 ) || ( perpSeg1 == limit ) ) ) return [];
|
||||
return [ inSeg1Pt1 ];
|
||||
}
|
||||
if ( perpSeg2 == limit ) {
|
||||
if ( ( inExcludeAdjacentSegs ) &&
|
||||
( ( perpSeg1 == 0 ) || ( perpSeg1 == limit ) ) ) return [];
|
||||
return [ inSeg1Pt2 ];
|
||||
}
|
||||
// intersection at endpoint of segment#2?
|
||||
if ( perpSeg1 == 0 ) return [ inSeg2Pt1 ];
|
||||
if ( perpSeg1 == limit ) return [ inSeg2Pt2 ];
|
||||
|
||||
// return real intersection point
|
||||
var factorSeg1 = perpSeg2 / limit;
|
||||
return [ { x: inSeg1Pt1.x + factorSeg1 * seg1dx,
|
||||
y: inSeg1Pt1.y + factorSeg1 * seg1dy } ];
|
||||
|
||||
} else { // parallel or colinear
|
||||
if ( ( perpSeg1 != 0 ) ||
|
||||
( seg2dy * seg1seg2dx != seg2dx * seg1seg2dy ) ) return [];
|
||||
|
||||
// they are collinear or degenerate
|
||||
var seg1Pt = ( (seg1dx == 0) && (seg1dy == 0) ); // segment1 ist just a point?
|
||||
var seg2Pt = ( (seg2dx == 0) && (seg2dy == 0) ); // segment2 ist just a point?
|
||||
// both segments are points
|
||||
if ( seg1Pt && seg2Pt ) {
|
||||
if ( (inSeg1Pt1.x != inSeg2Pt1.x) ||
|
||||
(inSeg1Pt1.y != inSeg2Pt1.y) ) return []; // they are distinct points
|
||||
return [ inSeg1Pt1 ]; // they are the same point
|
||||
}
|
||||
// segment#1 is a single point
|
||||
if ( seg1Pt ) {
|
||||
if (! point_in_segment_2D_colin( inSeg2Pt1, inSeg2Pt2, inSeg1Pt1 ) ) return []; // but not in segment#2
|
||||
return [ inSeg1Pt1 ];
|
||||
}
|
||||
// segment#2 is a single point
|
||||
if ( seg2Pt ) {
|
||||
if (! point_in_segment_2D_colin( inSeg1Pt1, inSeg1Pt2, inSeg2Pt1 ) ) return []; // but not in segment#1
|
||||
return [ inSeg2Pt1 ];
|
||||
}
|
||||
|
||||
// they are collinear segments, which might overlap
|
||||
var seg1min, seg1max, seg1minVal, seg1maxVal;
|
||||
var seg2min, seg2max, seg2minVal, seg2maxVal;
|
||||
if (seg1dx != 0) { // the segments are NOT on a vertical line
|
||||
if ( inSeg1Pt1.x < inSeg1Pt2.x ) {
|
||||
seg1min = inSeg1Pt1; seg1minVal = inSeg1Pt1.x;
|
||||
seg1max = inSeg1Pt2; seg1maxVal = inSeg1Pt2.x;
|
||||
} else {
|
||||
seg1min = inSeg1Pt2; seg1minVal = inSeg1Pt2.x;
|
||||
seg1max = inSeg1Pt1; seg1maxVal = inSeg1Pt1.x;
|
||||
}
|
||||
if ( inSeg2Pt1.x < inSeg2Pt2.x ) {
|
||||
seg2min = inSeg2Pt1; seg2minVal = inSeg2Pt1.x;
|
||||
seg2max = inSeg2Pt2; seg2maxVal = inSeg2Pt2.x;
|
||||
} else {
|
||||
seg2min = inSeg2Pt2; seg2minVal = inSeg2Pt2.x;
|
||||
seg2max = inSeg2Pt1; seg2maxVal = inSeg2Pt1.x;
|
||||
}
|
||||
} else { // the segments are on a vertical line
|
||||
if ( inSeg1Pt1.y < inSeg1Pt2.y ) {
|
||||
seg1min = inSeg1Pt1; seg1minVal = inSeg1Pt1.y;
|
||||
seg1max = inSeg1Pt2; seg1maxVal = inSeg1Pt2.y;
|
||||
} else {
|
||||
seg1min = inSeg1Pt2; seg1minVal = inSeg1Pt2.y;
|
||||
seg1max = inSeg1Pt1; seg1maxVal = inSeg1Pt1.y;
|
||||
}
|
||||
if ( inSeg2Pt1.y < inSeg2Pt2.y ) {
|
||||
seg2min = inSeg2Pt1; seg2minVal = inSeg2Pt1.y;
|
||||
seg2max = inSeg2Pt2; seg2maxVal = inSeg2Pt2.y;
|
||||
} else {
|
||||
seg2min = inSeg2Pt2; seg2minVal = inSeg2Pt2.y;
|
||||
seg2max = inSeg2Pt1; seg2maxVal = inSeg2Pt1.y;
|
||||
}
|
||||
}
|
||||
if ( seg1minVal <= seg2minVal ) {
|
||||
if ( seg1maxVal < seg2minVal ) return [];
|
||||
if ( seg1maxVal == seg2minVal ) {
|
||||
if ( inExcludeAdjacentSegs ) return [];
|
||||
return [ seg2min ];
|
||||
}
|
||||
if ( seg1maxVal <= seg2maxVal ) return [ seg2min, seg1max ];
|
||||
return [ seg2min, seg2max ];
|
||||
} else {
|
||||
if ( seg1minVal > seg2maxVal ) return [];
|
||||
if ( seg1minVal == seg2maxVal ) {
|
||||
if ( inExcludeAdjacentSegs ) return [];
|
||||
return [ seg1min ];
|
||||
}
|
||||
if ( seg1maxVal <= seg2maxVal ) return [ seg1min, seg1max ];
|
||||
return [ seg1min, seg2max ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isPointInsideAngle( inVertex, inLegFromPt, inLegToPt, inOtherPt ) {
|
||||
// The order of legs is important
|
||||
|
||||
var EPSILON = 0.0000000001;
|
||||
|
||||
// translation of all points, so that Vertex is at (0,0)
|
||||
var legFromPtX = inLegFromPt.x - inVertex.x, legFromPtY = inLegFromPt.y - inVertex.y;
|
||||
var legToPtX = inLegToPt.x - inVertex.x, legToPtY = inLegToPt.y - inVertex.y;
|
||||
var otherPtX = inOtherPt.x - inVertex.x, otherPtY = inOtherPt.y - inVertex.y;
|
||||
|
||||
// main angle >0: < 180 deg.; 0: 180 deg.; <0: > 180 deg.
|
||||
var from2toAngle = legFromPtX * legToPtY - legFromPtY * legToPtX;
|
||||
var from2otherAngle = legFromPtX * otherPtY - legFromPtY * otherPtX;
|
||||
|
||||
if ( Math.abs(from2toAngle) > EPSILON ) { // angle != 180 deg.
|
||||
|
||||
var other2toAngle = otherPtX * legToPtY - otherPtY * legToPtX;
|
||||
// console.log( "from2to: " + from2toAngle + ", from2other: " + from2otherAngle + ", other2to: " + other2toAngle );
|
||||
|
||||
if ( from2toAngle > 0 ) { // main angle < 180 deg.
|
||||
return ( ( from2otherAngle >= 0 ) && ( other2toAngle >= 0 ) );
|
||||
} else { // main angle > 180 deg.
|
||||
return ( ( from2otherAngle >= 0 ) || ( other2toAngle >= 0 ) );
|
||||
}
|
||||
} else { // angle == 180 deg.
|
||||
// console.log( "from2to: 180 deg., from2other: " + from2otherAngle );
|
||||
return ( from2otherAngle > 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function removeHoles( contour, holes ) {
|
||||
|
||||
var shape = contour.concat(); // work on this shape
|
||||
var hole;
|
||||
|
||||
function isCutLineInsideAngles( inShapeIdx, inHoleIdx ) {
|
||||
// Check if hole point lies within angle around shape point
|
||||
var lastShapeIdx = shape.length - 1;
|
||||
|
||||
var prevShapeIdx = inShapeIdx - 1;
|
||||
if ( prevShapeIdx < 0 ) prevShapeIdx = lastShapeIdx;
|
||||
|
||||
var nextShapeIdx = inShapeIdx + 1;
|
||||
if ( nextShapeIdx > lastShapeIdx ) nextShapeIdx = 0;
|
||||
|
||||
var insideAngle = isPointInsideAngle( shape[inShapeIdx], shape[ prevShapeIdx ], shape[ nextShapeIdx ], hole[inHoleIdx] );
|
||||
if (! insideAngle ) {
|
||||
// console.log( "Vertex (Shape): " + inShapeIdx + ", Point: " + hole[inHoleIdx].x + "/" + hole[inHoleIdx].y );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if shape point lies within angle around hole point
|
||||
var lastHoleIdx = hole.length - 1;
|
||||
|
||||
var prevHoleIdx = inHoleIdx - 1;
|
||||
if ( prevHoleIdx < 0 ) prevHoleIdx = lastHoleIdx;
|
||||
|
||||
var nextHoleIdx = inHoleIdx + 1;
|
||||
if ( nextHoleIdx > lastHoleIdx ) nextHoleIdx = 0;
|
||||
|
||||
insideAngle = isPointInsideAngle( hole[inHoleIdx], hole[ prevHoleIdx ], hole[ nextHoleIdx ], shape[inShapeIdx] );
|
||||
if (! insideAngle ) {
|
||||
// console.log( "Vertex (Hole): " + inHoleIdx + ", Point: " + shape[inShapeIdx].x + "/" + shape[inShapeIdx].y );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function intersectsShapeEdge( inShapePt, inHolePt ) {
|
||||
// checks for intersections with shape edges
|
||||
var sIdx, nextIdx, intersection;
|
||||
for ( sIdx = 0; sIdx < shape.length; sIdx ++ ) {
|
||||
nextIdx = sIdx+1; nextIdx %= shape.length;
|
||||
intersection = intersect_segments_2D( inShapePt, inHolePt, shape[sIdx], shape[nextIdx], true );
|
||||
if ( intersection.length > 0 ) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var indepHoles = [];
|
||||
|
||||
function intersectsHoleEdge( inShapePt, inHolePt ) {
|
||||
// checks for intersections with hole edges
|
||||
var ihIdx, chkHole,
|
||||
hIdx, nextIdx, intersection;
|
||||
for ( ihIdx = 0; ihIdx < indepHoles.length; ihIdx ++ ) {
|
||||
chkHole = holes[indepHoles[ihIdx]];
|
||||
for ( hIdx = 0; hIdx < chkHole.length; hIdx ++ ) {
|
||||
nextIdx = hIdx+1; nextIdx %= chkHole.length;
|
||||
intersection = intersect_segments_2D( inShapePt, inHolePt, chkHole[hIdx], chkHole[nextIdx], true );
|
||||
if ( intersection.length > 0 ) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var holeIndex, shapeIndex,
|
||||
shapePt, holePt,
|
||||
holeIdx, cutKey, failedCuts = [],
|
||||
tmpShape1, tmpShape2,
|
||||
tmpHole1, tmpHole2;
|
||||
|
||||
for ( var h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
indepHoles.push( h );
|
||||
|
||||
}
|
||||
|
||||
var minShapeIndex = 0;
|
||||
var counter = indepHoles.length * 2;
|
||||
while ( indepHoles.length > 0 ) {
|
||||
counter --;
|
||||
if ( counter < 0 ) {
|
||||
console.log( "Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!" );
|
||||
break;
|
||||
}
|
||||
|
||||
// search for shape-vertex and hole-vertex,
|
||||
// which can be connected without intersections
|
||||
for ( shapeIndex = minShapeIndex; shapeIndex < shape.length; shapeIndex ++ ) {
|
||||
|
||||
shapePt = shape[ shapeIndex ];
|
||||
holeIndex = - 1;
|
||||
|
||||
// search for hole which can be reached without intersections
|
||||
for ( var h = 0; h < indepHoles.length; h ++ ) {
|
||||
holeIdx = indepHoles[h];
|
||||
|
||||
// prevent multiple checks
|
||||
cutKey = shapePt.x + ":" + shapePt.y + ":" + holeIdx;
|
||||
if ( failedCuts[cutKey] !== undefined ) continue;
|
||||
|
||||
hole = holes[holeIdx];
|
||||
for ( var h2 = 0; h2 < hole.length; h2 ++ ) {
|
||||
holePt = hole[ h2 ];
|
||||
if (! isCutLineInsideAngles( shapeIndex, h2 ) ) continue;
|
||||
if ( intersectsShapeEdge( shapePt, holePt ) ) continue;
|
||||
if ( intersectsHoleEdge( shapePt, holePt ) ) continue;
|
||||
|
||||
holeIndex = h2;
|
||||
indepHoles.splice(h,1);
|
||||
|
||||
tmpShape1 = shape.slice( 0, shapeIndex+1 );
|
||||
tmpShape2 = shape.slice( shapeIndex );
|
||||
tmpHole1 = hole.slice( holeIndex );
|
||||
tmpHole2 = hole.slice( 0, holeIndex+1 );
|
||||
|
||||
shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 );
|
||||
|
||||
minShapeIndex = shapeIndex;
|
||||
|
||||
// Debug only, to show the selected cuts
|
||||
// glob_CutLines.push( [ shapePt, holePt ] );
|
||||
|
||||
break;
|
||||
}
|
||||
if ( holeIndex >= 0 ) break; // hole-vertex found
|
||||
|
||||
failedCuts[cutKey] = true; // remember failure
|
||||
}
|
||||
if ( holeIndex >= 0 ) break; // hole-vertex found
|
||||
}
|
||||
}
|
||||
|
||||
return shape; /* shape with no holes */
|
||||
}
|
||||
|
||||
|
||||
var i, il, f, face,
|
||||
key, index,
|
||||
allPointsMap = {};
|
||||
|
||||
// To maintain reference to old shape, one must match coordinates, or offset the indices from original arrays. It's probably easier to do the first.
|
||||
|
||||
var allpoints = contour.concat();
|
||||
|
||||
for ( var h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
Array.prototype.push.apply( allpoints, holes[h] );
|
||||
|
||||
}
|
||||
|
||||
//console.log( "allpoints",allpoints, allpoints.length );
|
||||
|
||||
// prepare all points map
|
||||
|
||||
for ( i = 0, il = allpoints.length; i < il; i ++ ) {
|
||||
|
||||
key = allpoints[ i ].x + ":" + allpoints[ i ].y;
|
||||
|
||||
if ( allPointsMap[ key ] !== undefined ) {
|
||||
|
||||
console.log( "Duplicate point", key );
|
||||
|
||||
}
|
||||
|
||||
allPointsMap[ key ] = i;
|
||||
|
||||
}
|
||||
|
||||
// remove holes by cutting paths to holes and adding them to the shape
|
||||
var shapeWithoutHoles = removeHoles( contour, holes );
|
||||
|
||||
var triangles = THREE.FontUtils.Triangulate( shapeWithoutHoles, false ); // True returns indices for points of spooled shape
|
||||
//console.log( "triangles",triangles, triangles.length );
|
||||
|
||||
// check all face vertices against all points map
|
||||
|
||||
for ( i = 0, il = triangles.length; i < il; i ++ ) {
|
||||
|
||||
face = triangles[ i ];
|
||||
|
||||
for ( f = 0; f < 3; f ++ ) {
|
||||
|
||||
key = face[ f ].x + ":" + face[ f ].y;
|
||||
|
||||
index = allPointsMap[ key ];
|
||||
|
||||
if ( index !== undefined ) {
|
||||
|
||||
face[ f ] = index;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return triangles.concat();
|
||||
|
||||
},
|
||||
|
||||
isClockWise: function ( pts ) {
|
||||
|
||||
return THREE.FontUtils.Triangulate.area( pts ) < 0;
|
||||
|
||||
},
|
||||
|
||||
// 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 );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
/**************************************************************
|
||||
* Arc curve
|
||||
**************************************************************/
|
||||
|
||||
THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
|
||||
|
||||
THREE.EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
|
||||
};
|
||||
|
||||
THREE.ArcCurve.prototype = Object.create( THREE.EllipseCurve.prototype );
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/**************************************************************
|
||||
* Closed Spline 3D curve
|
||||
**************************************************************/
|
||||
|
||||
|
||||
THREE.ClosedSplineCurve3 = THREE.Curve.create(
|
||||
|
||||
function ( points /* array of Vector3 */) {
|
||||
|
||||
this.points = (points == undefined) ? [] : points;
|
||||
|
||||
},
|
||||
|
||||
function ( t ) {
|
||||
|
||||
var v = new THREE.Vector3();
|
||||
var c = [];
|
||||
var points = this.points, point, intPoint, weight;
|
||||
point = ( points.length - 0 ) * t;
|
||||
// This needs to be from 0-length +1
|
||||
|
||||
intPoint = Math.floor( point );
|
||||
weight = point - intPoint;
|
||||
|
||||
intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length;
|
||||
c[ 0 ] = ( intPoint - 1 ) % points.length;
|
||||
c[ 1 ] = ( intPoint ) % points.length;
|
||||
c[ 2 ] = ( intPoint + 1 ) % points.length;
|
||||
c[ 3 ] = ( intPoint + 2 ) % points.length;
|
||||
|
||||
v.x = THREE.Curve.utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
|
||||
v.y = THREE.Curve.utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
|
||||
v.z = THREE.Curve.utils.interpolate( points[ c[ 0 ] ].z, points[ c[ 1 ] ].z, points[ c[ 2 ] ].z, points[ c[ 3 ] ].z, weight );
|
||||
|
||||
return v;
|
||||
|
||||
}
|
||||
|
||||
);
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/**************************************************************
|
||||
* Cubic Bezier curve
|
||||
**************************************************************/
|
||||
|
||||
THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
|
||||
|
||||
this.v0 = v0;
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
this.v3 = v3;
|
||||
|
||||
};
|
||||
|
||||
THREE.CubicBezierCurve.prototype = Object.create( THREE.Curve.prototype );
|
||||
|
||||
THREE.CubicBezierCurve.prototype.getPoint = function ( t ) {
|
||||
|
||||
var tx, ty;
|
||||
|
||||
tx = THREE.Shape.utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
|
||||
ty = THREE.Shape.utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
|
||||
|
||||
return new THREE.Vector2( tx, ty );
|
||||
|
||||
};
|
||||
|
||||
THREE.CubicBezierCurve.prototype.getTangent = function( t ) {
|
||||
|
||||
var tx, ty;
|
||||
|
||||
tx = THREE.Curve.utils.tangentCubicBezier( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
|
||||
ty = THREE.Curve.utils.tangentCubicBezier( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
|
||||
|
||||
var tangent = new THREE.Vector2( tx, ty );
|
||||
tangent.normalize();
|
||||
|
||||
return tangent;
|
||||
|
||||
};
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/**************************************************************
|
||||
* Cubic Bezier 3D curve
|
||||
**************************************************************/
|
||||
|
||||
THREE.CubicBezierCurve3 = THREE.Curve.create(
|
||||
|
||||
function ( v0, v1, v2, v3 ) {
|
||||
|
||||
this.v0 = v0;
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
this.v3 = v3;
|
||||
|
||||
},
|
||||
|
||||
function ( t ) {
|
||||
|
||||
var tx, ty, tz;
|
||||
|
||||
tx = THREE.Shape.utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
|
||||
ty = THREE.Shape.utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
|
||||
tz = THREE.Shape.utils.b3( t, this.v0.z, this.v1.z, this.v2.z, this.v3.z );
|
||||
|
||||
return new THREE.Vector3( tx, ty, tz );
|
||||
|
||||
}
|
||||
|
||||
);
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/**************************************************************
|
||||
* Ellipse curve
|
||||
**************************************************************/
|
||||
|
||||
THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise ) {
|
||||
|
||||
this.aX = aX;
|
||||
this.aY = aY;
|
||||
|
||||
this.xRadius = xRadius;
|
||||
this.yRadius = yRadius;
|
||||
|
||||
this.aStartAngle = aStartAngle;
|
||||
this.aEndAngle = aEndAngle;
|
||||
|
||||
this.aClockwise = aClockwise;
|
||||
|
||||
};
|
||||
|
||||
THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype );
|
||||
|
||||
THREE.EllipseCurve.prototype.getPoint = function ( t ) {
|
||||
|
||||
var angle;
|
||||
var deltaAngle = this.aEndAngle - this.aStartAngle;
|
||||
|
||||
if ( deltaAngle < 0 ) deltaAngle += Math.PI * 2;
|
||||
if ( deltaAngle > Math.PI * 2 ) deltaAngle -= Math.PI * 2;
|
||||
|
||||
if ( this.aClockwise === true ) {
|
||||
|
||||
angle = this.aEndAngle + ( 1 - t ) * ( Math.PI * 2 - deltaAngle );
|
||||
|
||||
} else {
|
||||
|
||||
angle = this.aStartAngle + t * deltaAngle;
|
||||
|
||||
}
|
||||
|
||||
var tx = this.aX + this.xRadius * Math.cos( angle );
|
||||
var ty = this.aY + this.yRadius * Math.sin( angle );
|
||||
|
||||
return new THREE.Vector2( tx, ty );
|
||||
|
||||
};
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/**************************************************************
|
||||
* Line
|
||||
**************************************************************/
|
||||
|
||||
THREE.LineCurve = function ( v1, v2 ) {
|
||||
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
|
||||
};
|
||||
|
||||
THREE.LineCurve.prototype = Object.create( THREE.Curve.prototype );
|
||||
|
||||
THREE.LineCurve.prototype.getPoint = function ( t ) {
|
||||
|
||||
var point = this.v2.clone().sub(this.v1);
|
||||
point.multiplyScalar( t ).add( this.v1 );
|
||||
|
||||
return point;
|
||||
|
||||
};
|
||||
|
||||
// Line curve is linear, so we can overwrite default getPointAt
|
||||
|
||||
THREE.LineCurve.prototype.getPointAt = function ( u ) {
|
||||
|
||||
return this.getPoint( u );
|
||||
|
||||
};
|
||||
|
||||
THREE.LineCurve.prototype.getTangent = function( t ) {
|
||||
|
||||
var tangent = this.v2.clone().sub(this.v1);
|
||||
|
||||
return tangent.normalize();
|
||||
|
||||
};
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/**************************************************************
|
||||
* Line3D
|
||||
**************************************************************/
|
||||
|
||||
THREE.LineCurve3 = THREE.Curve.create(
|
||||
|
||||
function ( v1, v2 ) {
|
||||
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
|
||||
},
|
||||
|
||||
function ( t ) {
|
||||
|
||||
var r = new THREE.Vector3();
|
||||
|
||||
|
||||
r.subVectors( this.v2, this.v1 ); // diff
|
||||
r.multiplyScalar( t );
|
||||
r.add( this.v1 );
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
);
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/**************************************************************
|
||||
* Quadratic Bezier curve
|
||||
**************************************************************/
|
||||
|
||||
|
||||
THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) {
|
||||
|
||||
this.v0 = v0;
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
|
||||
};
|
||||
|
||||
THREE.QuadraticBezierCurve.prototype = Object.create( THREE.Curve.prototype );
|
||||
|
||||
|
||||
THREE.QuadraticBezierCurve.prototype.getPoint = function ( t ) {
|
||||
|
||||
var tx, ty;
|
||||
|
||||
tx = THREE.Shape.utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
|
||||
ty = THREE.Shape.utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
|
||||
|
||||
return new THREE.Vector2( tx, ty );
|
||||
|
||||
};
|
||||
|
||||
|
||||
THREE.QuadraticBezierCurve.prototype.getTangent = function( t ) {
|
||||
|
||||
var tx, ty;
|
||||
|
||||
tx = THREE.Curve.utils.tangentQuadraticBezier( t, this.v0.x, this.v1.x, this.v2.x );
|
||||
ty = THREE.Curve.utils.tangentQuadraticBezier( t, this.v0.y, this.v1.y, this.v2.y );
|
||||
|
||||
// returns unit vector
|
||||
|
||||
var tangent = new THREE.Vector2( tx, ty );
|
||||
tangent.normalize();
|
||||
|
||||
return tangent;
|
||||
|
||||
};
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/**************************************************************
|
||||
* Quadratic Bezier 3D curve
|
||||
**************************************************************/
|
||||
|
||||
THREE.QuadraticBezierCurve3 = THREE.Curve.create(
|
||||
|
||||
function ( v0, v1, v2 ) {
|
||||
|
||||
this.v0 = v0;
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
|
||||
},
|
||||
|
||||
function ( t ) {
|
||||
|
||||
var tx, ty, tz;
|
||||
|
||||
tx = THREE.Shape.utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
|
||||
ty = THREE.Shape.utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
|
||||
tz = THREE.Shape.utils.b2( t, this.v0.z, this.v1.z, this.v2.z );
|
||||
|
||||
return new THREE.Vector3( tx, ty, tz );
|
||||
|
||||
}
|
||||
|
||||
);
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/**************************************************************
|
||||
* Spline curve
|
||||
**************************************************************/
|
||||
|
||||
THREE.SplineCurve = function ( points /* array of Vector2 */ ) {
|
||||
|
||||
this.points = (points == undefined) ? [] : points;
|
||||
|
||||
};
|
||||
|
||||
THREE.SplineCurve.prototype = Object.create( THREE.Curve.prototype );
|
||||
|
||||
THREE.SplineCurve.prototype.getPoint = function ( t ) {
|
||||
|
||||
var v = new THREE.Vector2();
|
||||
var c = [];
|
||||
var points = this.points, point, intPoint, weight;
|
||||
point = ( points.length - 1 ) * t;
|
||||
|
||||
intPoint = Math.floor( point );
|
||||
weight = point - intPoint;
|
||||
|
||||
c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
|
||||
c[ 1 ] = intPoint;
|
||||
c[ 2 ] = intPoint > points.length - 2 ? points.length -1 : intPoint + 1;
|
||||
c[ 3 ] = intPoint > points.length - 3 ? points.length -1 : intPoint + 2;
|
||||
|
||||
v.x = THREE.Curve.utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
|
||||
v.y = THREE.Curve.utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
|
||||
|
||||
return v;
|
||||
|
||||
};
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/**************************************************************
|
||||
* Spline 3D curve
|
||||
**************************************************************/
|
||||
|
||||
|
||||
THREE.SplineCurve3 = THREE.Curve.create(
|
||||
|
||||
function ( points /* array of Vector3 */) {
|
||||
|
||||
this.points = (points == undefined) ? [] : points;
|
||||
|
||||
},
|
||||
|
||||
function ( t ) {
|
||||
|
||||
var v = new THREE.Vector3();
|
||||
var c = [];
|
||||
var points = this.points, point, intPoint, weight;
|
||||
point = ( points.length - 1 ) * t;
|
||||
|
||||
intPoint = Math.floor( point );
|
||||
weight = point - intPoint;
|
||||
|
||||
c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
|
||||
c[ 1 ] = intPoint;
|
||||
c[ 2 ] = intPoint > points.length - 2 ? points.length - 1 : intPoint + 1;
|
||||
c[ 3 ] = intPoint > points.length - 3 ? points.length - 1 : intPoint + 2;
|
||||
|
||||
var pt0 = points[ c[0] ],
|
||||
pt1 = points[ c[1] ],
|
||||
pt2 = points[ c[2] ],
|
||||
pt3 = points[ c[3] ];
|
||||
|
||||
v.x = THREE.Curve.utils.interpolate(pt0.x, pt1.x, pt2.x, pt3.x, weight);
|
||||
v.y = THREE.Curve.utils.interpolate(pt0.y, pt1.y, pt2.y, pt3.y, weight);
|
||||
v.z = THREE.Curve.utils.interpolate(pt0.z, pt1.z, pt2.z, pt3.z, weight);
|
||||
|
||||
return v;
|
||||
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
|
||||
// THREE.SplineCurve3.prototype.getTangent = function(t) {
|
||||
// var v = new THREE.Vector3();
|
||||
// var c = [];
|
||||
// var points = this.points, point, intPoint, weight;
|
||||
// point = ( points.length - 1 ) * t;
|
||||
|
||||
// intPoint = Math.floor( point );
|
||||
// weight = point - intPoint;
|
||||
|
||||
// c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
|
||||
// c[ 1 ] = intPoint;
|
||||
// c[ 2 ] = intPoint > points.length - 2 ? points.length - 1 : intPoint + 1;
|
||||
// c[ 3 ] = intPoint > points.length - 3 ? points.length - 1 : intPoint + 2;
|
||||
|
||||
// var pt0 = points[ c[0] ],
|
||||
// pt1 = points[ c[1] ],
|
||||
// pt2 = points[ c[2] ],
|
||||
// pt3 = points[ c[3] ];
|
||||
|
||||
// // t = weight;
|
||||
// v.x = THREE.Curve.Utils.tangentSpline( t, pt0.x, pt1.x, pt2.x, pt3.x );
|
||||
// v.y = THREE.Curve.Utils.tangentSpline( t, pt0.y, pt1.y, pt2.y, pt3.y );
|
||||
// v.z = THREE.Curve.Utils.tangentSpline( t, pt0.z, pt1.z, pt2.z, pt3.z );
|
||||
|
||||
// return v;
|
||||
|
||||
// }
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Cube.as
|
||||
*/
|
||||
|
||||
THREE.BoxGeometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
this.parameters = {
|
||||
width: width,
|
||||
height: height,
|
||||
depth: depth,
|
||||
widthSegments: widthSegments,
|
||||
heightSegments: heightSegments,
|
||||
depthSegments: depthSegments
|
||||
};
|
||||
|
||||
this.widthSegments = widthSegments || 1;
|
||||
this.heightSegments = heightSegments || 1;
|
||||
this.depthSegments = depthSegments || 1;
|
||||
|
||||
var scope = this;
|
||||
|
||||
var width_half = width / 2;
|
||||
var height_half = height / 2;
|
||||
var depth_half = depth / 2;
|
||||
|
||||
buildPlane( 'z', 'y', - 1, - 1, depth, height, width_half, 0 ); // px
|
||||
buildPlane( 'z', 'y', 1, - 1, depth, height, - width_half, 1 ); // nx
|
||||
buildPlane( 'x', 'z', 1, 1, width, depth, height_half, 2 ); // py
|
||||
buildPlane( 'x', 'z', 1, - 1, width, depth, - height_half, 3 ); // ny
|
||||
buildPlane( 'x', 'y', 1, - 1, width, height, depth_half, 4 ); // pz
|
||||
buildPlane( 'x', 'y', - 1, - 1, width, height, - depth_half, 5 ); // nz
|
||||
|
||||
function buildPlane( u, v, udir, vdir, width, height, depth, materialIndex ) {
|
||||
|
||||
var w, ix, iy,
|
||||
gridX = scope.widthSegments,
|
||||
gridY = scope.heightSegments,
|
||||
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 = scope.depthSegments;
|
||||
|
||||
} else if ( ( u === 'z' && v === 'y' ) || ( u === 'y' && v === 'z' ) ) {
|
||||
|
||||
w = 'x';
|
||||
gridX = scope.depthSegments;
|
||||
|
||||
}
|
||||
|
||||
var gridX1 = gridX + 1,
|
||||
gridY1 = gridY + 1,
|
||||
segment_width = width / gridX,
|
||||
segment_height = height / gridY,
|
||||
normal = new THREE.Vector3();
|
||||
|
||||
normal[ w ] = depth > 0 ? 1 : - 1;
|
||||
|
||||
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( 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;
|
||||
|
||||
var uva = new THREE.Vector2( ix / gridX, 1 - iy / gridY );
|
||||
var uvb = new THREE.Vector2( ix / gridX, 1 - ( iy + 1 ) / gridY );
|
||||
var uvc = new THREE.Vector2( ( ix + 1 ) / gridX, 1 - ( iy + 1 ) / gridY );
|
||||
var uvd = new THREE.Vector2( ( ix + 1 ) / gridX, 1 - iy / gridY );
|
||||
|
||||
var face = new THREE.Face3( a + offset, b + offset, d + offset );
|
||||
face.normal.copy( normal );
|
||||
face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
|
||||
face.materialIndex = materialIndex;
|
||||
|
||||
scope.faces.push( face );
|
||||
scope.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );
|
||||
|
||||
face = new THREE.Face3( b + offset, c + offset, d + offset );
|
||||
face.normal.copy( normal );
|
||||
face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
|
||||
face.materialIndex = materialIndex;
|
||||
|
||||
scope.faces.push( face );
|
||||
scope.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.mergeVertices();
|
||||
|
||||
};
|
||||
|
||||
THREE.BoxGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/**
|
||||
* @author hughes
|
||||
*/
|
||||
|
||||
THREE.CircleGeometry = function ( radius, segments, thetaStart, thetaLength ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
segments: segments,
|
||||
thetaStart: thetaStart,
|
||||
thetaLength: thetaLength
|
||||
};
|
||||
|
||||
radius = radius || 50;
|
||||
segments = segments !== undefined ? Math.max( 3, segments ) : 8;
|
||||
|
||||
thetaStart = thetaStart !== undefined ? thetaStart : 0;
|
||||
thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
|
||||
|
||||
var i, uvs = [],
|
||||
center = new THREE.Vector3(), centerUV = new THREE.Vector2( 0.5, 0.5 );
|
||||
|
||||
this.vertices.push(center);
|
||||
uvs.push( centerUV );
|
||||
|
||||
for ( i = 0; i <= segments; i ++ ) {
|
||||
|
||||
var vertex = new THREE.Vector3();
|
||||
var segment = thetaStart + i / segments * thetaLength;
|
||||
|
||||
vertex.x = radius * Math.cos( segment );
|
||||
vertex.y = radius * Math.sin( segment );
|
||||
|
||||
this.vertices.push( vertex );
|
||||
uvs.push( new THREE.Vector2( ( vertex.x / radius + 1 ) / 2, ( vertex.y / radius + 1 ) / 2 ) );
|
||||
|
||||
}
|
||||
|
||||
var n = new THREE.Vector3( 0, 0, 1 );
|
||||
|
||||
for ( i = 1; i <= segments; i ++ ) {
|
||||
|
||||
this.faces.push( new THREE.Face3( i, i + 1, 0, [ n.clone(), n.clone(), n.clone() ] ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uvs[ i ].clone(), uvs[ i + 1 ].clone(), centerUV.clone() ] );
|
||||
|
||||
}
|
||||
|
||||
this.computeFaceNormals();
|
||||
|
||||
this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
|
||||
|
||||
};
|
||||
|
||||
THREE.CircleGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
|
||||
THREE.CubeGeometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {
|
||||
|
||||
console.warn( 'THEE.CubeGeometry has been renamed to THREE.BoxGeometry.' );
|
||||
return new THREE.BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments );
|
||||
|
||||
};
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
this.parameters = {
|
||||
radiusTop: radiusTop,
|
||||
radiusBottom: radiusBottom,
|
||||
height: height,
|
||||
radialSegments: radialSegments,
|
||||
heightSegments: heightSegments,
|
||||
openEnded: openEnded
|
||||
};
|
||||
|
||||
radiusTop = radiusTop !== undefined ? radiusTop : 20;
|
||||
radiusBottom = radiusBottom !== undefined ? radiusBottom : 20;
|
||||
height = height !== undefined ? height : 100;
|
||||
|
||||
radialSegments = radialSegments || 8;
|
||||
heightSegments = heightSegments || 1;
|
||||
|
||||
openEnded = openEnded !== undefined ? openEnded : false;
|
||||
|
||||
var heightHalf = height / 2;
|
||||
|
||||
var x, y, vertices = [], uvs = [];
|
||||
|
||||
for ( y = 0; y <= heightSegments; y ++ ) {
|
||||
|
||||
var verticesRow = [];
|
||||
var uvsRow = [];
|
||||
|
||||
var v = y / heightSegments;
|
||||
var radius = v * ( radiusBottom - radiusTop ) + radiusTop;
|
||||
|
||||
for ( x = 0; x <= radialSegments; x ++ ) {
|
||||
|
||||
var u = x / radialSegments;
|
||||
|
||||
var vertex = new THREE.Vector3();
|
||||
vertex.x = radius * Math.sin( u * Math.PI * 2 );
|
||||
vertex.y = - v * height + heightHalf;
|
||||
vertex.z = radius * Math.cos( u * Math.PI * 2 );
|
||||
|
||||
this.vertices.push( vertex );
|
||||
|
||||
verticesRow.push( this.vertices.length - 1 );
|
||||
uvsRow.push( new THREE.Vector2( u, 1 - v ) );
|
||||
|
||||
}
|
||||
|
||||
vertices.push( verticesRow );
|
||||
uvs.push( uvsRow );
|
||||
|
||||
}
|
||||
|
||||
var tanTheta = ( radiusBottom - radiusTop ) / height;
|
||||
var na, nb;
|
||||
|
||||
for ( x = 0; x < radialSegments; x ++ ) {
|
||||
|
||||
if ( radiusTop !== 0 ) {
|
||||
|
||||
na = this.vertices[ vertices[ 0 ][ x ] ].clone();
|
||||
nb = this.vertices[ vertices[ 0 ][ x + 1 ] ].clone();
|
||||
|
||||
} else {
|
||||
|
||||
na = this.vertices[ vertices[ 1 ][ x ] ].clone();
|
||||
nb = this.vertices[ vertices[ 1 ][ x + 1 ] ].clone();
|
||||
|
||||
}
|
||||
|
||||
na.setY( Math.sqrt( na.x * na.x + na.z * na.z ) * tanTheta ).normalize();
|
||||
nb.setY( Math.sqrt( nb.x * nb.x + nb.z * nb.z ) * tanTheta ).normalize();
|
||||
|
||||
for ( y = 0; y < heightSegments; y ++ ) {
|
||||
|
||||
var v1 = vertices[ y ][ x ];
|
||||
var v2 = vertices[ y + 1 ][ x ];
|
||||
var v3 = vertices[ y + 1 ][ x + 1 ];
|
||||
var v4 = vertices[ y ][ x + 1 ];
|
||||
|
||||
var n1 = na.clone();
|
||||
var n2 = na.clone();
|
||||
var n3 = nb.clone();
|
||||
var n4 = nb.clone();
|
||||
|
||||
var uv1 = uvs[ y ][ x ].clone();
|
||||
var uv2 = uvs[ y + 1 ][ x ].clone();
|
||||
var uv3 = uvs[ y + 1 ][ x + 1 ].clone();
|
||||
var uv4 = uvs[ y ][ x + 1 ].clone();
|
||||
|
||||
this.faces.push( new THREE.Face3( v1, v2, v4, [ n1, n2, n4 ] ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv4 ] );
|
||||
|
||||
this.faces.push( new THREE.Face3( v2, v3, v4, [ n2.clone(), n3, n4.clone() ] ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uv2.clone(), uv3, uv4.clone() ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// top cap
|
||||
|
||||
if ( openEnded === false && radiusTop > 0 ) {
|
||||
|
||||
this.vertices.push( new THREE.Vector3( 0, heightHalf, 0 ) );
|
||||
|
||||
for ( x = 0; x < radialSegments; x ++ ) {
|
||||
|
||||
var v1 = vertices[ 0 ][ x ];
|
||||
var v2 = vertices[ 0 ][ x + 1 ];
|
||||
var v3 = this.vertices.length - 1;
|
||||
|
||||
var n1 = new THREE.Vector3( 0, 1, 0 );
|
||||
var n2 = new THREE.Vector3( 0, 1, 0 );
|
||||
var n3 = new THREE.Vector3( 0, 1, 0 );
|
||||
|
||||
var uv1 = uvs[ 0 ][ x ].clone();
|
||||
var uv2 = uvs[ 0 ][ x + 1 ].clone();
|
||||
var uv3 = new THREE.Vector2( uv2.x, 0 );
|
||||
|
||||
this.faces.push( new THREE.Face3( v1, v2, v3, [ n1, n2, n3 ] ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3 ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// bottom cap
|
||||
|
||||
if ( openEnded === false && radiusBottom > 0 ) {
|
||||
|
||||
this.vertices.push( new THREE.Vector3( 0, - heightHalf, 0 ) );
|
||||
|
||||
for ( x = 0; x < radialSegments; x ++ ) {
|
||||
|
||||
var v1 = vertices[ y ][ x + 1 ];
|
||||
var v2 = vertices[ y ][ x ];
|
||||
var v3 = this.vertices.length - 1;
|
||||
|
||||
var n1 = new THREE.Vector3( 0, - 1, 0 );
|
||||
var n2 = new THREE.Vector3( 0, - 1, 0 );
|
||||
var n3 = new THREE.Vector3( 0, - 1, 0 );
|
||||
|
||||
var uv1 = uvs[ y ][ x + 1 ].clone();
|
||||
var uv2 = uvs[ y ][ x ].clone();
|
||||
var uv3 = new THREE.Vector2( uv2.x, 1 );
|
||||
|
||||
this.faces.push( new THREE.Face3( v1, v2, v3, [ n1, n2, n3 ] ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3 ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.computeFaceNormals();
|
||||
|
||||
}
|
||||
|
||||
THREE.CylinderGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,699 +0,0 @@
|
|||
/**
|
||||
* @author zz85 / http://www.lab4games.net/zz85/blog
|
||||
*
|
||||
* Creates extruded geometry from a path shape.
|
||||
*
|
||||
* parameters = {
|
||||
*
|
||||
* curveSegments: <int>, // number of points on the curves
|
||||
* steps: <int>, // number of points for z-side extrusions / used for subdividing segements of extrude spline too
|
||||
* amount: <int>, // Depth to extrude the shape
|
||||
*
|
||||
* bevelEnabled: <bool>, // turn on bevel
|
||||
* bevelThickness: <float>, // how deep into the original shape bevel goes
|
||||
* bevelSize: <float>, // how far from shape outline is bevel
|
||||
* bevelSegments: <int>, // number of bevel layers
|
||||
*
|
||||
* extrudePath: <THREE.CurvePath> // 3d spline path to extrude shape along. (creates Frames if .frames aren't defined)
|
||||
* frames: <THREE.TubeGeometry.FrenetFrames> // containing arrays of tangents, normals, binormals
|
||||
*
|
||||
* material: <int> // material index for front and back faces
|
||||
* extrudeMaterial: <int> // material index for extrusion and beveled faces
|
||||
* uvGenerator: <Object> // object that provides UV generator functions
|
||||
*
|
||||
* }
|
||||
**/
|
||||
|
||||
THREE.ExtrudeGeometry = function ( shapes, options ) {
|
||||
|
||||
if ( typeof( shapes ) === "undefined" ) {
|
||||
shapes = [];
|
||||
return;
|
||||
}
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
shapes = shapes instanceof Array ? shapes : [ shapes ];
|
||||
|
||||
this.addShapeList( shapes, options );
|
||||
|
||||
this.computeFaceNormals();
|
||||
|
||||
// can't really use automatic vertex normals
|
||||
// as then front and back sides get smoothed too
|
||||
// should do separate smoothing just for sides
|
||||
|
||||
//this.computeVertexNormals();
|
||||
|
||||
//console.log( "took", ( Date.now() - startTime ) );
|
||||
|
||||
};
|
||||
|
||||
THREE.ExtrudeGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
||||
THREE.ExtrudeGeometry.prototype.addShapeList = function ( shapes, options ) {
|
||||
var sl = shapes.length;
|
||||
|
||||
for ( var s = 0; s < sl; s ++ ) {
|
||||
var shape = shapes[ s ];
|
||||
this.addShape( shape, options );
|
||||
}
|
||||
};
|
||||
|
||||
THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) {
|
||||
|
||||
var amount = options.amount !== undefined ? options.amount : 100;
|
||||
|
||||
var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10
|
||||
var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8
|
||||
var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
|
||||
|
||||
var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false
|
||||
|
||||
var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
|
||||
|
||||
var steps = options.steps !== undefined ? options.steps : 1;
|
||||
|
||||
var extrudePath = options.extrudePath;
|
||||
var extrudePts, extrudeByPath = false;
|
||||
|
||||
var material = options.material;
|
||||
var extrudeMaterial = options.extrudeMaterial;
|
||||
|
||||
// Use default WorldUVGenerator if no UV generators are specified.
|
||||
var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : THREE.ExtrudeGeometry.WorldUVGenerator;
|
||||
|
||||
var splineTube, binormal, normal, position2;
|
||||
if ( extrudePath ) {
|
||||
|
||||
extrudePts = extrudePath.getSpacedPoints( steps );
|
||||
|
||||
extrudeByPath = true;
|
||||
bevelEnabled = false; // bevels not supported for path extrusion
|
||||
|
||||
// SETUP TNB variables
|
||||
|
||||
// Reuse TNB from TubeGeomtry for now.
|
||||
// TODO1 - have a .isClosed in spline?
|
||||
|
||||
splineTube = options.frames !== undefined ? options.frames : new THREE.TubeGeometry.FrenetFrames(extrudePath, steps, false);
|
||||
|
||||
// console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
|
||||
|
||||
binormal = new THREE.Vector3();
|
||||
normal = new THREE.Vector3();
|
||||
position2 = new THREE.Vector3();
|
||||
|
||||
}
|
||||
|
||||
// Safeguards if bevels are not enabled
|
||||
|
||||
if ( ! bevelEnabled ) {
|
||||
|
||||
bevelSegments = 0;
|
||||
bevelThickness = 0;
|
||||
bevelSize = 0;
|
||||
|
||||
}
|
||||
|
||||
// Variables initalization
|
||||
|
||||
var ahole, h, hl; // looping of holes
|
||||
var scope = this;
|
||||
var bevelPoints = [];
|
||||
|
||||
var shapesOffset = this.vertices.length;
|
||||
|
||||
var shapePoints = shape.extractPoints( curveSegments );
|
||||
|
||||
var vertices = shapePoints.shape;
|
||||
var holes = shapePoints.holes;
|
||||
|
||||
var reverse = ! THREE.Shape.utils.isClockWise( vertices ) ;
|
||||
|
||||
if ( reverse ) {
|
||||
|
||||
vertices = vertices.reverse();
|
||||
|
||||
// Maybe we should also check if holes are in the opposite direction, just to be safe ...
|
||||
|
||||
for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
ahole = holes[ h ];
|
||||
|
||||
if ( THREE.Shape.utils.isClockWise( ahole ) ) {
|
||||
|
||||
holes[ h ] = ahole.reverse();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
reverse = false; // If vertices are in order now, we shouldn't need to worry about them again (hopefully)!
|
||||
|
||||
}
|
||||
|
||||
|
||||
var faces = THREE.Shape.utils.triangulateShape ( vertices, holes );
|
||||
|
||||
/* Vertices */
|
||||
|
||||
var contour = vertices; // vertices has all points but contour has only points of circumference
|
||||
|
||||
for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
ahole = holes[ h ];
|
||||
|
||||
vertices = vertices.concat( ahole );
|
||||
|
||||
}
|
||||
|
||||
|
||||
function scalePt2 ( pt, vec, size ) {
|
||||
|
||||
if ( ! vec ) console.log( "die" );
|
||||
|
||||
return vec.clone().multiplyScalar( size ).add( pt );
|
||||
|
||||
}
|
||||
|
||||
var b, bs, t, z,
|
||||
vert, vlen = vertices.length,
|
||||
face, flen = faces.length,
|
||||
cont, clen = contour.length;
|
||||
|
||||
|
||||
// Find directions for point movement
|
||||
|
||||
var RAD_TO_DEGREES = 180 / Math.PI;
|
||||
|
||||
|
||||
function getBevelVec( inPt, inPrev, inNext ) {
|
||||
|
||||
var EPSILON = 0.0000000001;
|
||||
var sign = THREE.Math.sign;
|
||||
|
||||
// computes for inPt the corresponding point inPt' on a new contour
|
||||
// shiftet by 1 unit (length of normalized vector) to the left
|
||||
// if we walk along contour clockwise, this new contour is outside the old one
|
||||
//
|
||||
// inPt' is the intersection of the two lines parallel to the two
|
||||
// adjacent edges of inPt at a distance of 1 unit on the left side.
|
||||
|
||||
var v_trans_x, v_trans_y, shrink_by = 1; // resulting translation vector for inPt
|
||||
|
||||
// good reading for geometry algorithms (here: line-line intersection)
|
||||
// http://geomalgorithms.com/a05-_intersect-1.html
|
||||
|
||||
var v_prev_x = inPt.x - inPrev.x, v_prev_y = inPt.y - inPrev.y;
|
||||
var v_next_x = inNext.x - inPt.x, v_next_y = inNext.y - inPt.y;
|
||||
|
||||
var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
|
||||
|
||||
// check for colinear edges
|
||||
var colinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
|
||||
|
||||
if ( Math.abs( colinear0 ) > EPSILON ) { // not colinear
|
||||
|
||||
// length of vectors for normalizing
|
||||
|
||||
var v_prev_len = Math.sqrt( v_prev_lensq );
|
||||
var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
|
||||
|
||||
// shift adjacent points by unit vectors to the left
|
||||
|
||||
var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
|
||||
var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
|
||||
|
||||
var ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
|
||||
var ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
|
||||
|
||||
// scaling factor for v_prev to intersection point
|
||||
|
||||
var sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
|
||||
( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
|
||||
( v_prev_x * v_next_y - v_prev_y * v_next_x );
|
||||
|
||||
// vector from inPt to intersection point
|
||||
|
||||
v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
|
||||
v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
|
||||
|
||||
// Don't normalize!, otherwise sharp corners become ugly
|
||||
// but prevent crazy spikes
|
||||
var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y )
|
||||
if ( v_trans_lensq <= 2 ) {
|
||||
return new THREE.Vector2( v_trans_x, v_trans_y );
|
||||
} else {
|
||||
shrink_by = Math.sqrt( v_trans_lensq / 2 );
|
||||
}
|
||||
|
||||
} else { // handle special case of colinear edges
|
||||
|
||||
var direction_eq = false; // assumes: opposite
|
||||
if ( v_prev_x > EPSILON ) {
|
||||
if ( v_next_x > EPSILON ) { direction_eq = true; }
|
||||
} else {
|
||||
if ( v_prev_x < - EPSILON ) {
|
||||
if ( v_next_x < - EPSILON ) { direction_eq = true; }
|
||||
} else {
|
||||
if ( sign(v_prev_y) == sign(v_next_y) ) { direction_eq = true; }
|
||||
}
|
||||
}
|
||||
|
||||
if ( direction_eq ) {
|
||||
// console.log("Warning: lines are a straight sequence");
|
||||
v_trans_x = - v_prev_y;
|
||||
v_trans_y = v_prev_x;
|
||||
shrink_by = Math.sqrt( v_prev_lensq );
|
||||
} else {
|
||||
// console.log("Warning: lines are a straight spike");
|
||||
v_trans_x = v_prev_x;
|
||||
v_trans_y = v_prev_y;
|
||||
shrink_by = Math.sqrt( v_prev_lensq / 2 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new THREE.Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
|
||||
|
||||
}
|
||||
|
||||
|
||||
var contourMovements = [];
|
||||
|
||||
for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
|
||||
|
||||
if ( j === il ) j = 0;
|
||||
if ( k === il ) k = 0;
|
||||
|
||||
// (j)---(i)---(k)
|
||||
// console.log('i,j,k', i, j , k)
|
||||
|
||||
var pt_i = contour[ i ];
|
||||
var pt_j = contour[ j ];
|
||||
var pt_k = contour[ k ];
|
||||
|
||||
contourMovements[ i ]= getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
|
||||
|
||||
}
|
||||
|
||||
var holesMovements = [], oneHoleMovements, verticesMovements = contourMovements.concat();
|
||||
|
||||
for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
ahole = holes[ h ];
|
||||
|
||||
oneHoleMovements = [];
|
||||
|
||||
for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
|
||||
|
||||
if ( j === il ) j = 0;
|
||||
if ( k === il ) k = 0;
|
||||
|
||||
// (j)---(i)---(k)
|
||||
oneHoleMovements[ i ]= getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
|
||||
|
||||
}
|
||||
|
||||
holesMovements.push( oneHoleMovements );
|
||||
verticesMovements = verticesMovements.concat( oneHoleMovements );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Loop bevelSegments, 1 for the front, 1 for the back
|
||||
|
||||
for ( b = 0; b < bevelSegments; b ++ ) {
|
||||
//for ( b = bevelSegments; b > 0; b -- ) {
|
||||
|
||||
t = b / bevelSegments;
|
||||
z = bevelThickness * ( 1 - t );
|
||||
|
||||
//z = bevelThickness * t;
|
||||
bs = bevelSize * ( Math.sin ( t * Math.PI/2 ) ) ; // curved
|
||||
//bs = bevelSize * t ; // linear
|
||||
|
||||
// contract shape
|
||||
|
||||
for ( i = 0, il = contour.length; i < il; i ++ ) {
|
||||
|
||||
vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
|
||||
|
||||
v( vert.x, vert.y, - z );
|
||||
|
||||
}
|
||||
|
||||
// expand holes
|
||||
|
||||
for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
ahole = holes[ h ];
|
||||
oneHoleMovements = holesMovements[ h ];
|
||||
|
||||
for ( i = 0, il = ahole.length; i < il; i ++ ) {
|
||||
|
||||
vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
|
||||
|
||||
v( vert.x, vert.y, - z );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bs = bevelSize;
|
||||
|
||||
// Back facing vertices
|
||||
|
||||
for ( i = 0; i < vlen; i ++ ) {
|
||||
|
||||
vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
|
||||
|
||||
if ( ! extrudeByPath ) {
|
||||
|
||||
v( vert.x, vert.y, 0 );
|
||||
|
||||
} else {
|
||||
|
||||
// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
|
||||
|
||||
normal.copy( splineTube.normals[0] ).multiplyScalar(vert.x);
|
||||
binormal.copy( splineTube.binormals[0] ).multiplyScalar(vert.y);
|
||||
|
||||
position2.copy( extrudePts[0] ).add(normal).add(binormal);
|
||||
|
||||
v( position2.x, position2.y, position2.z );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add stepped vertices...
|
||||
// Including front facing vertices
|
||||
|
||||
var s;
|
||||
|
||||
for ( s = 1; s <= steps; s ++ ) {
|
||||
|
||||
for ( i = 0; i < vlen; i ++ ) {
|
||||
|
||||
vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
|
||||
|
||||
if ( ! extrudeByPath ) {
|
||||
|
||||
v( vert.x, vert.y, amount / steps * s );
|
||||
|
||||
} else {
|
||||
|
||||
// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
|
||||
|
||||
normal.copy( splineTube.normals[s] ).multiplyScalar( vert.x );
|
||||
binormal.copy( splineTube.binormals[s] ).multiplyScalar( vert.y );
|
||||
|
||||
position2.copy( extrudePts[s] ).add( normal ).add( binormal );
|
||||
|
||||
v( position2.x, position2.y, position2.z );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Add bevel segments planes
|
||||
|
||||
//for ( b = 1; b <= bevelSegments; b ++ ) {
|
||||
for ( b = bevelSegments - 1; b >= 0; b -- ) {
|
||||
|
||||
t = b / bevelSegments;
|
||||
z = bevelThickness * ( 1 - t );
|
||||
//bs = bevelSize * ( 1-Math.sin ( ( 1 - t ) * Math.PI/2 ) );
|
||||
bs = bevelSize * Math.sin ( t * Math.PI/2 ) ;
|
||||
|
||||
// contract shape
|
||||
|
||||
for ( i = 0, il = contour.length; i < il; i ++ ) {
|
||||
|
||||
vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
|
||||
v( vert.x, vert.y, amount + z );
|
||||
|
||||
}
|
||||
|
||||
// expand holes
|
||||
|
||||
for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
ahole = holes[ h ];
|
||||
oneHoleMovements = holesMovements[ h ];
|
||||
|
||||
for ( i = 0, il = ahole.length; i < il; i ++ ) {
|
||||
|
||||
vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
|
||||
|
||||
if ( ! extrudeByPath ) {
|
||||
|
||||
v( vert.x, vert.y, amount + z );
|
||||
|
||||
} else {
|
||||
|
||||
v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Faces */
|
||||
|
||||
// Top and bottom faces
|
||||
|
||||
buildLidFaces();
|
||||
|
||||
// Sides faces
|
||||
|
||||
buildSideFaces();
|
||||
|
||||
|
||||
///// Internal functions
|
||||
|
||||
function buildLidFaces() {
|
||||
|
||||
if ( bevelEnabled ) {
|
||||
|
||||
var layer = 0 ; // steps + 1
|
||||
var offset = vlen * layer;
|
||||
|
||||
// Bottom faces
|
||||
|
||||
for ( i = 0; i < flen; i ++ ) {
|
||||
|
||||
face = faces[ i ];
|
||||
f3( face[ 2 ]+ offset, face[ 1 ]+ offset, face[ 0 ] + offset, true );
|
||||
|
||||
}
|
||||
|
||||
layer = steps + bevelSegments * 2;
|
||||
offset = vlen * layer;
|
||||
|
||||
// Top faces
|
||||
|
||||
for ( i = 0; i < flen; i ++ ) {
|
||||
|
||||
face = faces[ i ];
|
||||
f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset, false );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Bottom faces
|
||||
|
||||
for ( i = 0; i < flen; i ++ ) {
|
||||
|
||||
face = faces[ i ];
|
||||
f3( face[ 2 ], face[ 1 ], face[ 0 ], true );
|
||||
|
||||
}
|
||||
|
||||
// Top faces
|
||||
|
||||
for ( i = 0; i < flen; i ++ ) {
|
||||
|
||||
face = faces[ i ];
|
||||
f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps, false );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Create faces for the z-sides of the shape
|
||||
|
||||
function buildSideFaces() {
|
||||
|
||||
var layeroffset = 0;
|
||||
sidewalls( contour, layeroffset );
|
||||
layeroffset += contour.length;
|
||||
|
||||
for ( h = 0, hl = holes.length; h < hl; h ++ ) {
|
||||
|
||||
ahole = holes[ h ];
|
||||
sidewalls( ahole, layeroffset );
|
||||
|
||||
//, true
|
||||
layeroffset += ahole.length;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function sidewalls( contour, layeroffset ) {
|
||||
|
||||
var j, k;
|
||||
i = contour.length;
|
||||
|
||||
while ( --i >= 0 ) {
|
||||
|
||||
j = i;
|
||||
k = i - 1;
|
||||
if ( k < 0 ) k = contour.length - 1;
|
||||
|
||||
//console.log('b', i,j, i-1, k,vertices.length);
|
||||
|
||||
var s = 0, sl = steps + bevelSegments * 2;
|
||||
|
||||
for ( s = 0; s < sl; s ++ ) {
|
||||
|
||||
var slen1 = vlen * s;
|
||||
var slen2 = vlen * ( s + 1 );
|
||||
|
||||
var a = layeroffset + j + slen1,
|
||||
b = layeroffset + k + slen1,
|
||||
c = layeroffset + k + slen2,
|
||||
d = layeroffset + j + slen2;
|
||||
|
||||
f4( a, b, c, d, contour, s, sl, j, k );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function v( x, y, z ) {
|
||||
|
||||
scope.vertices.push( new THREE.Vector3( x, y, z ) );
|
||||
|
||||
}
|
||||
|
||||
function f3( a, b, c, isBottom ) {
|
||||
|
||||
a += shapesOffset;
|
||||
b += shapesOffset;
|
||||
c += shapesOffset;
|
||||
|
||||
// normal, color, material
|
||||
scope.faces.push( new THREE.Face3( a, b, c, null, null, material ) );
|
||||
|
||||
var uvs = isBottom ? uvgen.generateBottomUV( scope, shape, options, a, b, c ) : uvgen.generateTopUV( scope, shape, options, a, b, c );
|
||||
|
||||
scope.faceVertexUvs[ 0 ].push( uvs );
|
||||
|
||||
}
|
||||
|
||||
function f4( a, b, c, d, wallContour, stepIndex, stepsLength, contourIndex1, contourIndex2 ) {
|
||||
|
||||
a += shapesOffset;
|
||||
b += shapesOffset;
|
||||
c += shapesOffset;
|
||||
d += shapesOffset;
|
||||
|
||||
scope.faces.push( new THREE.Face3( a, b, d, null, null, extrudeMaterial ) );
|
||||
scope.faces.push( new THREE.Face3( b, c, d, null, null, extrudeMaterial ) );
|
||||
|
||||
var uvs = uvgen.generateSideWallUV( scope, shape, wallContour, options, a, b, c, d,
|
||||
stepIndex, stepsLength, contourIndex1, contourIndex2 );
|
||||
|
||||
scope.faceVertexUvs[ 0 ].push( [ uvs[ 0 ], uvs[ 1 ], uvs[ 3 ] ] );
|
||||
scope.faceVertexUvs[ 0 ].push( [ uvs[ 1 ], uvs[ 2 ], uvs[ 3 ] ] );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.ExtrudeGeometry.WorldUVGenerator = {
|
||||
|
||||
generateTopUV: function( geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC ) {
|
||||
var ax = geometry.vertices[ indexA ].x,
|
||||
ay = geometry.vertices[ indexA ].y,
|
||||
|
||||
bx = geometry.vertices[ indexB ].x,
|
||||
by = geometry.vertices[ indexB ].y,
|
||||
|
||||
cx = geometry.vertices[ indexC ].x,
|
||||
cy = geometry.vertices[ indexC ].y;
|
||||
|
||||
return [
|
||||
new THREE.Vector2( ax, ay ),
|
||||
new THREE.Vector2( bx, by ),
|
||||
new THREE.Vector2( cx, cy )
|
||||
];
|
||||
|
||||
},
|
||||
|
||||
generateBottomUV: function( geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC ) {
|
||||
|
||||
return this.generateTopUV( geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC );
|
||||
|
||||
},
|
||||
|
||||
generateSideWallUV: function( geometry, extrudedShape, wallContour, extrudeOptions,
|
||||
indexA, indexB, indexC, indexD, stepIndex, stepsLength,
|
||||
contourIndex1, contourIndex2 ) {
|
||||
|
||||
var ax = geometry.vertices[ indexA ].x,
|
||||
ay = geometry.vertices[ indexA ].y,
|
||||
az = geometry.vertices[ indexA ].z,
|
||||
|
||||
bx = geometry.vertices[ indexB ].x,
|
||||
by = geometry.vertices[ indexB ].y,
|
||||
bz = geometry.vertices[ indexB ].z,
|
||||
|
||||
cx = geometry.vertices[ indexC ].x,
|
||||
cy = geometry.vertices[ indexC ].y,
|
||||
cz = geometry.vertices[ indexC ].z,
|
||||
|
||||
dx = geometry.vertices[ indexD ].x,
|
||||
dy = geometry.vertices[ indexD ].y,
|
||||
dz = geometry.vertices[ indexD ].z;
|
||||
|
||||
if ( Math.abs( ay - by ) < 0.01 ) {
|
||||
return [
|
||||
new THREE.Vector2( ax, 1 - az ),
|
||||
new THREE.Vector2( bx, 1 - bz ),
|
||||
new THREE.Vector2( cx, 1 - cz ),
|
||||
new THREE.Vector2( dx, 1 - dz )
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
new THREE.Vector2( ay, 1 - az ),
|
||||
new THREE.Vector2( by, 1 - bz ),
|
||||
new THREE.Vector2( cy, 1 - cz ),
|
||||
new THREE.Vector2( dy, 1 - dz )
|
||||
];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
THREE.ExtrudeGeometry.__v1 = new THREE.Vector2();
|
||||
THREE.ExtrudeGeometry.__v2 = new THREE.Vector2();
|
||||
THREE.ExtrudeGeometry.__v3 = new THREE.Vector2();
|
||||
THREE.ExtrudeGeometry.__v4 = new THREE.Vector2();
|
||||
THREE.ExtrudeGeometry.__v5 = new THREE.Vector2();
|
||||
THREE.ExtrudeGeometry.__v6 = new THREE.Vector2();
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/**
|
||||
* @author timothypratley / https://github.com/timothypratley
|
||||
*/
|
||||
|
||||
THREE.IcosahedronGeometry = function ( radius, detail ) {
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
detail: detail
|
||||
};
|
||||
|
||||
var t = ( 1 + Math.sqrt( 5 ) ) / 2;
|
||||
|
||||
var vertices = [
|
||||
- 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0,
|
||||
0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t,
|
||||
t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1
|
||||
];
|
||||
|
||||
var indices = [
|
||||
0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11,
|
||||
1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
|
||||
3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9,
|
||||
4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1
|
||||
];
|
||||
|
||||
THREE.PolyhedronGeometry.call( this, vertices, indices, radius, detail );
|
||||
|
||||
};
|
||||
|
||||
THREE.IcosahedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
/**
|
||||
* @author astrodud / http://astrodud.isgreat.org/
|
||||
* @author zz85 / https://github.com/zz85
|
||||
* @author bhouston / http://exocortex.com
|
||||
*/
|
||||
|
||||
// points - to create a closed torus, one must use a set of points
|
||||
// like so: [ a, b, c, d, a ], see first is the same as last.
|
||||
// segments - the number of circumference segments to create
|
||||
// phiStart - the starting radian
|
||||
// phiLength - the radian (0 to 2*PI) range of the lathed section
|
||||
// 2*pi is a closed lathe, less than 2PI is a portion.
|
||||
THREE.LatheGeometry = function ( points, segments, phiStart, phiLength ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
segments = segments || 12;
|
||||
phiStart = phiStart || 0;
|
||||
phiLength = phiLength || 2 * Math.PI;
|
||||
|
||||
var inversePointLength = 1.0 / ( points.length - 1 );
|
||||
var inverseSegments = 1.0 / segments;
|
||||
|
||||
for ( var i = 0, il = segments; i <= il; i ++ ) {
|
||||
|
||||
var phi = phiStart + i * inverseSegments * phiLength;
|
||||
|
||||
var c = Math.cos( phi ),
|
||||
s = Math.sin( phi );
|
||||
|
||||
for ( var j = 0, jl = points.length; j < jl; j ++ ) {
|
||||
|
||||
var pt = points[ j ];
|
||||
|
||||
var vertex = new THREE.Vector3();
|
||||
|
||||
vertex.x = c * pt.x - s * pt.y;
|
||||
vertex.y = s * pt.x + c * pt.y;
|
||||
vertex.z = pt.z;
|
||||
|
||||
this.vertices.push( vertex );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var np = points.length;
|
||||
|
||||
for ( var i = 0, il = segments; i < il; i ++ ) {
|
||||
|
||||
for ( var j = 0, jl = points.length - 1; j < jl; j ++ ) {
|
||||
|
||||
var base = j + np * i;
|
||||
var a = base;
|
||||
var b = base + np;
|
||||
var c = base + 1 + np;
|
||||
var d = base + 1;
|
||||
|
||||
var u0 = i * inverseSegments;
|
||||
var v0 = j * inversePointLength;
|
||||
var u1 = u0 + inverseSegments;
|
||||
var v1 = v0 + inversePointLength;
|
||||
|
||||
this.faces.push( new THREE.Face3( a, b, d ) );
|
||||
|
||||
this.faceVertexUvs[ 0 ].push( [
|
||||
|
||||
new THREE.Vector2( u0, v0 ),
|
||||
new THREE.Vector2( u1, v0 ),
|
||||
new THREE.Vector2( u0, v1 )
|
||||
|
||||
] );
|
||||
|
||||
this.faces.push( new THREE.Face3( b, c, d ) );
|
||||
|
||||
this.faceVertexUvs[ 0 ].push( [
|
||||
|
||||
new THREE.Vector2( u1, v0 ),
|
||||
new THREE.Vector2( u1, v1 ),
|
||||
new THREE.Vector2( u0, v1 )
|
||||
|
||||
] );
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.mergeVertices();
|
||||
this.computeFaceNormals();
|
||||
this.computeVertexNormals();
|
||||
|
||||
};
|
||||
|
||||
THREE.LatheGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/**
|
||||
* @author timothypratley / https://github.com/timothypratley
|
||||
*/
|
||||
|
||||
THREE.OctahedronGeometry = function ( radius, detail ) {
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
detail: detail
|
||||
};
|
||||
|
||||
var vertices = [
|
||||
1, 0, 0, - 1, 0, 0, 0, 1, 0, 0,- 1, 0, 0, 0, 1, 0, 0,- 1
|
||||
];
|
||||
|
||||
var indices = [
|
||||
0, 2, 4, 0, 4, 3, 0, 3, 5, 0, 5, 2, 1, 2, 5, 1, 5, 3, 1, 3, 4, 1, 4, 2
|
||||
];
|
||||
|
||||
THREE.PolyhedronGeometry.call( this, vertices, indices, radius, detail );
|
||||
};
|
||||
|
||||
THREE.OctahedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
/**
|
||||
* @author zz85 / https://github.com/zz85
|
||||
* Parametric Surfaces Geometry
|
||||
* based on the brilliant article by @prideout http://prideout.net/blog/?p=44
|
||||
*
|
||||
* new THREE.ParametricGeometry( parametricFunction, uSegments, ySegements );
|
||||
*
|
||||
*/
|
||||
|
||||
THREE.ParametricGeometry = function ( func, slices, stacks ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
var verts = this.vertices;
|
||||
var faces = this.faces;
|
||||
var uvs = this.faceVertexUvs[ 0 ];
|
||||
|
||||
var i, il, j, p;
|
||||
var u, v;
|
||||
|
||||
var stackCount = stacks + 1;
|
||||
var sliceCount = slices + 1;
|
||||
|
||||
for ( i = 0; i <= stacks; i ++ ) {
|
||||
|
||||
v = i / stacks;
|
||||
|
||||
for ( j = 0; j <= slices; j ++ ) {
|
||||
|
||||
u = j / slices;
|
||||
|
||||
p = func( u, v );
|
||||
verts.push( p );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var a, b, c, d;
|
||||
var uva, uvb, uvc, uvd;
|
||||
|
||||
for ( i = 0; i < stacks; i ++ ) {
|
||||
|
||||
for ( j = 0; j < slices; j ++ ) {
|
||||
|
||||
a = i * sliceCount + j;
|
||||
b = i * sliceCount + j + 1;
|
||||
c = (i + 1) * sliceCount + j + 1;
|
||||
d = (i + 1) * sliceCount + j;
|
||||
|
||||
uva = new THREE.Vector2( j / slices, i / stacks );
|
||||
uvb = new THREE.Vector2( ( j + 1 ) / slices, i / stacks );
|
||||
uvc = new THREE.Vector2( ( j + 1 ) / slices, ( i + 1 ) / stacks );
|
||||
uvd = new THREE.Vector2( j / slices, ( i + 1 ) / stacks );
|
||||
|
||||
faces.push( new THREE.Face3( a, b, d ) );
|
||||
uvs.push( [ uva, uvb, uvd ] );
|
||||
|
||||
faces.push( new THREE.Face3( b, c, d ) );
|
||||
uvs.push( [ uvb.clone(), uvc, uvd.clone() ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// console.log(this);
|
||||
|
||||
// magic bullet
|
||||
// var diff = this.mergeVertices();
|
||||
// console.log('removed ', diff, ' vertices by merging');
|
||||
|
||||
this.computeFaceNormals();
|
||||
this.computeVertexNormals();
|
||||
|
||||
};
|
||||
|
||||
THREE.ParametricGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / 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, widthSegments, heightSegments ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
this.parameters = {
|
||||
width: width,
|
||||
height: height,
|
||||
widthSegments: widthSegments,
|
||||
heightSegments: heightSegments
|
||||
};
|
||||
|
||||
var ix, iz;
|
||||
var width_half = width / 2;
|
||||
var height_half = height / 2;
|
||||
|
||||
var gridX = widthSegments || 1;
|
||||
var gridZ = heightSegments || 1;
|
||||
|
||||
var gridX1 = gridX + 1;
|
||||
var gridZ1 = gridZ + 1;
|
||||
|
||||
var segment_width = width / gridX;
|
||||
var segment_height = height / gridZ;
|
||||
|
||||
var normal = new THREE.Vector3( 0, 0, 1 );
|
||||
|
||||
for ( iz = 0; iz < gridZ1; iz ++ ) {
|
||||
|
||||
var y = iz * segment_height - height_half;
|
||||
|
||||
for ( ix = 0; ix < gridX1; ix ++ ) {
|
||||
|
||||
var x = ix * segment_width - width_half;
|
||||
|
||||
this.vertices.push( new THREE.Vector3( x, - y, 0 ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for ( iz = 0; iz < gridZ; iz ++ ) {
|
||||
|
||||
for ( ix = 0; ix < gridX; ix ++ ) {
|
||||
|
||||
var a = ix + gridX1 * iz;
|
||||
var b = ix + gridX1 * ( iz + 1 );
|
||||
var c = ( ix + 1 ) + gridX1 * ( iz + 1 );
|
||||
var d = ( ix + 1 ) + gridX1 * iz;
|
||||
|
||||
var uva = new THREE.Vector2( ix / gridX, 1 - iz / gridZ );
|
||||
var uvb = new THREE.Vector2( ix / gridX, 1 - ( iz + 1 ) / gridZ );
|
||||
var uvc = new THREE.Vector2( ( ix + 1 ) / gridX, 1 - ( iz + 1 ) / gridZ );
|
||||
var uvd = new THREE.Vector2( ( ix + 1 ) / gridX, 1 - iz / gridZ );
|
||||
|
||||
var face = new THREE.Face3( a, b, d );
|
||||
face.normal.copy( normal );
|
||||
face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
|
||||
|
||||
this.faces.push( face );
|
||||
this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );
|
||||
|
||||
face = new THREE.Face3( b, c, d );
|
||||
face.normal.copy( normal );
|
||||
face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
|
||||
|
||||
this.faces.push( face );
|
||||
this.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.PlaneGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,226 +0,0 @@
|
|||
/**
|
||||
* @author clockworkgeek / https://github.com/clockworkgeek
|
||||
* @author timothypratley / https://github.com/timothypratley
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
*/
|
||||
|
||||
THREE.PolyhedronGeometry = function ( vertices, indices, radius, detail ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
radius = radius || 1;
|
||||
detail = detail || 0;
|
||||
|
||||
var that = this;
|
||||
|
||||
for ( var i = 0, l = vertices.length; i < l; i += 3 ) {
|
||||
|
||||
prepare( new THREE.Vector3( vertices[ i ], vertices[ i + 1 ], vertices[ i + 2 ] ) );
|
||||
|
||||
}
|
||||
|
||||
var midpoints = [], p = this.vertices;
|
||||
|
||||
var faces = [];
|
||||
|
||||
for ( var i = 0, j = 0, l = indices.length; i < l; i += 3, j ++ ) {
|
||||
|
||||
var v1 = p[ indices[ i ] ];
|
||||
var v2 = p[ indices[ i + 1 ] ];
|
||||
var v3 = p[ indices[ i + 2 ] ];
|
||||
|
||||
faces[ j ] = new THREE.Face3( v1.index, v2.index, v3.index, [ v1.clone(), v2.clone(), v3.clone() ] );
|
||||
|
||||
}
|
||||
|
||||
var centroid = new THREE.Vector3();
|
||||
|
||||
for ( var i = 0, l = faces.length; i < l; i ++ ) {
|
||||
|
||||
subdivide( faces[ i ], detail );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Handle case when face straddles the seam
|
||||
|
||||
for ( var i = 0, l = this.faceVertexUvs[ 0 ].length; i < l; i ++ ) {
|
||||
|
||||
var uvs = this.faceVertexUvs[ 0 ][ i ];
|
||||
|
||||
var x0 = uvs[ 0 ].x;
|
||||
var x1 = uvs[ 1 ].x;
|
||||
var x2 = uvs[ 2 ].x;
|
||||
|
||||
var max = Math.max( x0, Math.max( x1, x2 ) );
|
||||
var min = Math.min( x0, Math.min( x1, x2 ) );
|
||||
|
||||
if ( max > 0.9 && min < 0.1 ) { // 0.9 is somewhat arbitrary
|
||||
|
||||
if ( x0 < 0.2 ) uvs[ 0 ].x += 1;
|
||||
if ( x1 < 0.2 ) uvs[ 1 ].x += 1;
|
||||
if ( x2 < 0.2 ) uvs[ 2 ].x += 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Apply radius
|
||||
|
||||
for ( var i = 0, l = this.vertices.length; i < l; i ++ ) {
|
||||
|
||||
this.vertices[ i ].multiplyScalar( radius );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Merge vertices
|
||||
|
||||
this.mergeVertices();
|
||||
|
||||
this.computeFaceNormals();
|
||||
|
||||
this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
|
||||
|
||||
|
||||
// Project vector onto sphere's surface
|
||||
|
||||
function prepare( vector ) {
|
||||
|
||||
var vertex = vector.normalize().clone();
|
||||
vertex.index = that.vertices.push( vertex ) - 1;
|
||||
|
||||
// Texture coords are equivalent to map coords, calculate angle and convert to fraction of a circle.
|
||||
|
||||
var u = azimuth( vector ) / 2 / Math.PI + 0.5;
|
||||
var v = inclination( vector ) / Math.PI + 0.5;
|
||||
vertex.uv = new THREE.Vector2( u, 1 - v );
|
||||
|
||||
return vertex;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Approximate a curved face with recursively sub-divided triangles.
|
||||
|
||||
function make( v1, v2, v3 ) {
|
||||
|
||||
var face = new THREE.Face3( v1.index, v2.index, v3.index, [ v1.clone(), v2.clone(), v3.clone() ] );
|
||||
that.faces.push( face );
|
||||
|
||||
centroid.copy( v1 ).add( v2 ).add( v3 ).divideScalar( 3 );
|
||||
|
||||
var azi = azimuth( centroid );
|
||||
|
||||
that.faceVertexUvs[ 0 ].push( [
|
||||
correctUV( v1.uv, v1, azi ),
|
||||
correctUV( v2.uv, v2, azi ),
|
||||
correctUV( v3.uv, v3, azi )
|
||||
] );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Analytically subdivide a face to the required detail level.
|
||||
|
||||
function subdivide( face, detail ) {
|
||||
|
||||
var cols = Math.pow(2, detail);
|
||||
var cells = Math.pow(4, detail);
|
||||
var a = prepare( that.vertices[ face.a ] );
|
||||
var b = prepare( that.vertices[ face.b ] );
|
||||
var c = prepare( that.vertices[ face.c ] );
|
||||
var v = [];
|
||||
|
||||
// Construct all of the vertices for this subdivision.
|
||||
|
||||
for ( var i = 0 ; i <= cols; i ++ ) {
|
||||
|
||||
v[ i ] = [];
|
||||
|
||||
var aj = prepare( a.clone().lerp( c, i / cols ) );
|
||||
var bj = prepare( b.clone().lerp( c, i / cols ) );
|
||||
var rows = cols - i;
|
||||
|
||||
for ( var j = 0; j <= rows; j ++) {
|
||||
|
||||
if ( j == 0 && i == cols ) {
|
||||
|
||||
v[ i ][ j ] = aj;
|
||||
|
||||
} else {
|
||||
|
||||
v[ i ][ j ] = prepare( aj.clone().lerp( bj, j / rows ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Construct all of the faces.
|
||||
|
||||
for ( var i = 0; i < cols ; i ++ ) {
|
||||
|
||||
for ( var j = 0; j < 2 * (cols - i) - 1; j ++ ) {
|
||||
|
||||
var k = Math.floor( j / 2 );
|
||||
|
||||
if ( j % 2 == 0 ) {
|
||||
|
||||
make(
|
||||
v[ i ][ k + 1],
|
||||
v[ i + 1 ][ k ],
|
||||
v[ i ][ k ]
|
||||
);
|
||||
|
||||
} else {
|
||||
|
||||
make(
|
||||
v[ i ][ k + 1 ],
|
||||
v[ i + 1][ k + 1],
|
||||
v[ i + 1 ][ k ]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Angle around the Y axis, counter-clockwise when looking from above.
|
||||
|
||||
function azimuth( vector ) {
|
||||
|
||||
return Math.atan2( vector.z, - vector.x );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Angle above the XZ plane.
|
||||
|
||||
function inclination( vector ) {
|
||||
|
||||
return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Texture fixing helper. Spheres have some odd behaviours.
|
||||
|
||||
function correctUV( uv, vector, azimuth ) {
|
||||
|
||||
if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) uv = new THREE.Vector2( uv.x - 1, uv.y );
|
||||
if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) uv = new THREE.Vector2( azimuth / 2 / Math.PI + 0.5, uv.y );
|
||||
return uv.clone();
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
THREE.PolyhedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/**
|
||||
* @author Kaleb Murphy
|
||||
*/
|
||||
|
||||
THREE.RingGeometry = function ( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
innerRadius = innerRadius || 0;
|
||||
outerRadius = outerRadius || 50;
|
||||
|
||||
thetaStart = thetaStart !== undefined ? thetaStart : 0;
|
||||
thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
|
||||
|
||||
thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;
|
||||
phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 8;
|
||||
|
||||
var i, o, uvs = [], radius = innerRadius, radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
|
||||
|
||||
for ( i = 0; i < phiSegments + 1; i ++ ) { // concentric circles inside ring
|
||||
|
||||
for ( o = 0; o < thetaSegments + 1; o ++ ) { // number of segments per circle
|
||||
|
||||
var vertex = new THREE.Vector3();
|
||||
var segment = thetaStart + o / thetaSegments * thetaLength;
|
||||
vertex.x = radius * Math.cos( segment );
|
||||
vertex.y = radius * Math.sin( segment );
|
||||
|
||||
this.vertices.push( vertex );
|
||||
uvs.push( new THREE.Vector2( ( vertex.x / outerRadius + 1 ) / 2, ( vertex.y / outerRadius + 1 ) / 2 ) );
|
||||
}
|
||||
|
||||
radius += radiusStep;
|
||||
|
||||
}
|
||||
|
||||
var n = new THREE.Vector3( 0, 0, 1 );
|
||||
|
||||
for ( i = 0; i < phiSegments; i ++ ) { // concentric circles inside ring
|
||||
|
||||
var thetaSegment = i * (thetaSegments + 1);
|
||||
|
||||
for ( o = 0; o < thetaSegments ; o ++ ) { // number of segments per circle
|
||||
|
||||
var segment = o + thetaSegment;
|
||||
|
||||
var v1 = segment;
|
||||
var v2 = segment + thetaSegments + 1;
|
||||
var v3 = segment + thetaSegments + 2;
|
||||
|
||||
this.faces.push( new THREE.Face3( v1, v2, v3, [ n.clone(), n.clone(), n.clone() ] ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uvs[ v1 ].clone(), uvs[ v2 ].clone(), uvs[ v3 ].clone() ]);
|
||||
|
||||
v1 = segment;
|
||||
v2 = segment + thetaSegments + 2;
|
||||
v3 = segment + 1;
|
||||
|
||||
this.faces.push( new THREE.Face3( v1, v2, v3, [ n.clone(), n.clone(), n.clone() ] ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uvs[ v1 ].clone(), uvs[ v2 ].clone(), uvs[ v3 ].clone() ]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.computeFaceNormals();
|
||||
|
||||
this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
|
||||
|
||||
};
|
||||
|
||||
THREE.RingGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
/**
|
||||
* @author jonobr1 / http://jonobr1.com
|
||||
*
|
||||
* Creates a one-sided polygonal geometry from a path shape. Similar to
|
||||
* ExtrudeGeometry.
|
||||
*
|
||||
* parameters = {
|
||||
*
|
||||
* curveSegments: <int>, // number of points on the curves. NOT USED AT THE MOMENT.
|
||||
*
|
||||
* material: <int> // material index for front and back faces
|
||||
* uvGenerator: <Object> // object that provides UV generator functions
|
||||
*
|
||||
* }
|
||||
**/
|
||||
|
||||
THREE.ShapeGeometry = function ( shapes, options ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
if ( shapes instanceof Array === false ) shapes = [ shapes ];
|
||||
|
||||
this.addShapeList( shapes, options );
|
||||
|
||||
this.computeFaceNormals();
|
||||
|
||||
};
|
||||
|
||||
THREE.ShapeGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
||||
/**
|
||||
* Add an array of shapes to THREE.ShapeGeometry.
|
||||
*/
|
||||
THREE.ShapeGeometry.prototype.addShapeList = function ( shapes, options ) {
|
||||
|
||||
for ( var i = 0, l = shapes.length; i < l; i ++ ) {
|
||||
|
||||
this.addShape( shapes[ i ], options );
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a shape to THREE.ShapeGeometry, based on THREE.ExtrudeGeometry.
|
||||
*/
|
||||
THREE.ShapeGeometry.prototype.addShape = function ( shape, options ) {
|
||||
|
||||
if ( options === undefined ) options = {};
|
||||
var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
|
||||
|
||||
var material = options.material;
|
||||
var uvgen = options.UVGenerator === undefined ? THREE.ExtrudeGeometry.WorldUVGenerator : options.UVGenerator;
|
||||
|
||||
//
|
||||
|
||||
var i, l, hole, s;
|
||||
|
||||
var shapesOffset = this.vertices.length;
|
||||
var shapePoints = shape.extractPoints( curveSegments );
|
||||
|
||||
var vertices = shapePoints.shape;
|
||||
var holes = shapePoints.holes;
|
||||
|
||||
var reverse = ! THREE.Shape.utils.isClockWise( vertices );
|
||||
|
||||
if ( reverse ) {
|
||||
|
||||
vertices = vertices.reverse();
|
||||
|
||||
// Maybe we should also check if holes are in the opposite direction, just to be safe...
|
||||
|
||||
for ( i = 0, l = holes.length; i < l; i ++ ) {
|
||||
|
||||
hole = holes[ i ];
|
||||
|
||||
if ( THREE.Shape.utils.isClockWise( hole ) ) {
|
||||
|
||||
holes[ i ] = hole.reverse();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
reverse = false;
|
||||
|
||||
}
|
||||
|
||||
var faces = THREE.Shape.utils.triangulateShape( vertices, holes );
|
||||
|
||||
// Vertices
|
||||
|
||||
var contour = vertices;
|
||||
|
||||
for ( i = 0, l = holes.length; i < l; i ++ ) {
|
||||
|
||||
hole = holes[ i ];
|
||||
vertices = vertices.concat( hole );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var vert, vlen = vertices.length;
|
||||
var face, flen = faces.length;
|
||||
var cont, clen = contour.length;
|
||||
|
||||
for ( i = 0; i < vlen; i ++ ) {
|
||||
|
||||
vert = vertices[ i ];
|
||||
|
||||
this.vertices.push( new THREE.Vector3( vert.x, vert.y, 0 ) );
|
||||
|
||||
}
|
||||
|
||||
for ( i = 0; i < flen; i ++ ) {
|
||||
|
||||
face = faces[ i ];
|
||||
|
||||
var a = face[ 0 ] + shapesOffset;
|
||||
var b = face[ 1 ] + shapesOffset;
|
||||
var c = face[ 2 ] + shapesOffset;
|
||||
|
||||
this.faces.push( new THREE.Face3( a, b, c, null, null, material ) );
|
||||
this.faceVertexUvs[ 0 ].push( uvgen.generateBottomUV( this, shape, options, a, b, c ) );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.SphereGeometry = function ( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
widthSegments: widthSegments,
|
||||
heightSegments: heightSegments,
|
||||
phiStart: phiStart,
|
||||
phiLength: phiLength,
|
||||
thetaStart: thetaStart,
|
||||
thetaLength: thetaLength
|
||||
};
|
||||
|
||||
radius = radius || 50;
|
||||
|
||||
widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 );
|
||||
heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 );
|
||||
|
||||
phiStart = phiStart !== undefined ? phiStart : 0;
|
||||
phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
|
||||
|
||||
thetaStart = thetaStart !== undefined ? thetaStart : 0;
|
||||
thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
|
||||
|
||||
var x, y, vertices = [], uvs = [];
|
||||
|
||||
for ( y = 0; y <= heightSegments; y ++ ) {
|
||||
|
||||
var verticesRow = [];
|
||||
var uvsRow = [];
|
||||
|
||||
for ( x = 0; x <= widthSegments; x ++ ) {
|
||||
|
||||
var u = x / widthSegments;
|
||||
var v = y / heightSegments;
|
||||
|
||||
var vertex = new THREE.Vector3();
|
||||
vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
|
||||
vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
|
||||
vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
|
||||
|
||||
this.vertices.push( vertex );
|
||||
|
||||
verticesRow.push( this.vertices.length - 1 );
|
||||
uvsRow.push( new THREE.Vector2( u, 1 - v ) );
|
||||
|
||||
}
|
||||
|
||||
vertices.push( verticesRow );
|
||||
uvs.push( uvsRow );
|
||||
|
||||
}
|
||||
|
||||
for ( y = 0; y < heightSegments; y ++ ) {
|
||||
|
||||
for ( x = 0; x < widthSegments; x ++ ) {
|
||||
|
||||
var v1 = vertices[ y ][ x + 1 ];
|
||||
var v2 = vertices[ y ][ x ];
|
||||
var v3 = vertices[ y + 1 ][ x ];
|
||||
var v4 = vertices[ y + 1 ][ x + 1 ];
|
||||
|
||||
var n1 = this.vertices[ v1 ].clone().normalize();
|
||||
var n2 = this.vertices[ v2 ].clone().normalize();
|
||||
var n3 = this.vertices[ v3 ].clone().normalize();
|
||||
var n4 = this.vertices[ v4 ].clone().normalize();
|
||||
|
||||
var uv1 = uvs[ y ][ x + 1 ].clone();
|
||||
var uv2 = uvs[ y ][ x ].clone();
|
||||
var uv3 = uvs[ y + 1 ][ x ].clone();
|
||||
var uv4 = uvs[ y + 1 ][ x + 1 ].clone();
|
||||
|
||||
if ( Math.abs( this.vertices[ v1 ].y ) === radius ) {
|
||||
|
||||
uv1.x = ( uv1.x + uv2.x ) / 2;
|
||||
this.faces.push( new THREE.Face3( v1, v3, v4, [ n1, n3, n4 ] ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uv1, uv3, uv4 ] );
|
||||
|
||||
} else if ( Math.abs( this.vertices[ v3 ].y ) === radius ) {
|
||||
|
||||
uv3.x = ( uv3.x + uv4.x ) / 2;
|
||||
this.faces.push( new THREE.Face3( v1, v2, v3, [ n1, n2, n3 ] ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3 ] );
|
||||
|
||||
} else {
|
||||
|
||||
this.faces.push( new THREE.Face3( v1, v2, v4, [ n1, n2, n4 ] ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv4 ] );
|
||||
|
||||
this.faces.push( new THREE.Face3( v2, v3, v4, [ n2.clone(), n3, n4.clone() ] ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uv2.clone(), uv3, uv4.clone() ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.computeFaceNormals();
|
||||
|
||||
this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
|
||||
|
||||
};
|
||||
|
||||
THREE.SphereGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
/**
|
||||
* @author timothypratley / https://github.com/timothypratley
|
||||
*/
|
||||
|
||||
THREE.TetrahedronGeometry = function ( radius, detail ) {
|
||||
|
||||
var vertices = [
|
||||
1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1
|
||||
];
|
||||
|
||||
var indices = [
|
||||
2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1
|
||||
];
|
||||
|
||||
THREE.PolyhedronGeometry.call( this, vertices, indices, radius, detail );
|
||||
|
||||
};
|
||||
|
||||
THREE.TetrahedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/**
|
||||
* @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: <float>, // size of the text
|
||||
* height: <float>, // thickness to extrude text
|
||||
* curveSegments: <int>, // number of points on the curves
|
||||
*
|
||||
* font: <string>, // font name
|
||||
* weight: <string>, // font weight (normal, bold)
|
||||
* style: <string>, // font style (normal, italics)
|
||||
*
|
||||
* bevelEnabled: <bool>, // turn on bevel
|
||||
* bevelThickness: <float>, // how deep into text bevel goes
|
||||
* bevelSize: <float>, // how far from text outline is bevel
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
/* Usage Examples
|
||||
|
||||
// TextGeometry wrapper
|
||||
|
||||
var text3d = new TextGeometry( text, options );
|
||||
|
||||
// Complete manner
|
||||
|
||||
var textShapes = THREE.FontUtils.generateShapes( text, options );
|
||||
var text3d = new ExtrudeGeometry( textShapes, options );
|
||||
|
||||
*/
|
||||
|
||||
|
||||
THREE.TextGeometry = function ( text, parameters ) {
|
||||
|
||||
parameters = parameters || {};
|
||||
|
||||
var textShapes = THREE.FontUtils.generateShapes( text, parameters );
|
||||
|
||||
// translate parameters to ExtrudeGeometry API
|
||||
|
||||
parameters.amount = parameters.height !== undefined ? parameters.height : 50;
|
||||
|
||||
// defaults
|
||||
|
||||
if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
|
||||
if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
|
||||
if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
|
||||
|
||||
THREE.ExtrudeGeometry.call( this, textShapes, parameters );
|
||||
|
||||
};
|
||||
|
||||
THREE.TextGeometry.prototype = Object.create( THREE.ExtrudeGeometry.prototype );
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
/**
|
||||
* @author oosmoxiecode
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* 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, radialSegments, tubularSegments, arc ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
tube: tube,
|
||||
radialSegments: radialSegments,
|
||||
tubularSegments: tubularSegments,
|
||||
arc: arc
|
||||
};
|
||||
|
||||
radius = radius || 100;
|
||||
tube = tube || 40;
|
||||
radialSegments = radialSegments || 8;
|
||||
tubularSegments = tubularSegments || 6;
|
||||
arc = arc || Math.PI * 2;
|
||||
|
||||
var center = new THREE.Vector3(), uvs = [], normals = [];
|
||||
|
||||
for ( var j = 0; j <= radialSegments; j ++ ) {
|
||||
|
||||
for ( var i = 0; i <= tubularSegments; i ++ ) {
|
||||
|
||||
var u = i / tubularSegments * arc;
|
||||
var v = j / radialSegments * Math.PI * 2;
|
||||
|
||||
center.x = radius * Math.cos( u );
|
||||
center.y = radius * Math.sin( u );
|
||||
|
||||
var vertex = new THREE.Vector3();
|
||||
vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
|
||||
vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
|
||||
vertex.z = tube * Math.sin( v );
|
||||
|
||||
this.vertices.push( vertex );
|
||||
|
||||
uvs.push( new THREE.Vector2( i / tubularSegments, j / radialSegments ) );
|
||||
normals.push( vertex.clone().sub( center ).normalize() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for ( var j = 1; j <= radialSegments; j ++ ) {
|
||||
|
||||
for ( var i = 1; i <= tubularSegments; i ++ ) {
|
||||
|
||||
var a = ( tubularSegments + 1 ) * j + i - 1;
|
||||
var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
|
||||
var c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
|
||||
var d = ( tubularSegments + 1 ) * j + i;
|
||||
|
||||
var face = new THREE.Face3( a, b, d, [ normals[ a ].clone(), normals[ b ].clone(), normals[ d ].clone() ] );
|
||||
this.faces.push( face );
|
||||
this.faceVertexUvs[ 0 ].push( [ uvs[ a ].clone(), uvs[ b ].clone(), uvs[ d ].clone() ] );
|
||||
|
||||
face = new THREE.Face3( b, c, d, [ normals[ b ].clone(), normals[ c ].clone(), normals[ d ].clone() ] );
|
||||
this.faces.push( face );
|
||||
this.faceVertexUvs[ 0 ].push( [ uvs[ b ].clone(), uvs[ c ].clone(), uvs[ d ].clone() ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.computeFaceNormals();
|
||||
|
||||
};
|
||||
|
||||
THREE.TorusGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
/**
|
||||
* @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, radialSegments, tubularSegments, p, q, heightScale ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
this.parameters = {
|
||||
radius: radius,
|
||||
tube: tube,
|
||||
radialSegments: radialSegments,
|
||||
tubularSegments: tubularSegments,
|
||||
p: p,
|
||||
q: q,
|
||||
heightScale: heightScale
|
||||
};
|
||||
|
||||
radius = radius || 100;
|
||||
tube = tube || 40;
|
||||
radialSegments = radialSegments || 64;
|
||||
tubularSegments = tubularSegments || 8;
|
||||
p = p || 2;
|
||||
q = q || 3;
|
||||
heightScale = heightScale || 1;
|
||||
|
||||
var grid = new Array( radialSegments );
|
||||
var tang = new THREE.Vector3();
|
||||
var n = new THREE.Vector3();
|
||||
var bitan = new THREE.Vector3();
|
||||
|
||||
for ( var i = 0; i < radialSegments; ++ i ) {
|
||||
|
||||
grid[ i ] = new Array( tubularSegments );
|
||||
var u = i / radialSegments * 2 * p * Math.PI;
|
||||
var p1 = getPos( u, q, p, radius, heightScale );
|
||||
var p2 = getPos( u + 0.01, q, p, radius, heightScale );
|
||||
tang.subVectors( p2, p1 );
|
||||
n.addVectors( p2, p1 );
|
||||
|
||||
bitan.crossVectors( tang, n );
|
||||
n.crossVectors( bitan, tang );
|
||||
bitan.normalize();
|
||||
n.normalize();
|
||||
|
||||
for ( var j = 0; j < tubularSegments; ++ j ) {
|
||||
|
||||
var v = j / tubularSegments * 2 * Math.PI;
|
||||
var cx = - tube * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
|
||||
var cy = tube * Math.sin( v );
|
||||
|
||||
var pos = new THREE.Vector3();
|
||||
pos.x = p1.x + cx * n.x + cy * bitan.x;
|
||||
pos.y = p1.y + cx * n.y + cy * bitan.y;
|
||||
pos.z = p1.z + cx * n.z + cy * bitan.z;
|
||||
|
||||
grid[ i ][ j ] = this.vertices.push( pos ) - 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for ( var i = 0; i < radialSegments; ++ i ) {
|
||||
|
||||
for ( var j = 0; j < tubularSegments; ++ j ) {
|
||||
|
||||
var ip = ( i + 1 ) % radialSegments;
|
||||
var jp = ( j + 1 ) % tubularSegments;
|
||||
|
||||
var a = grid[ i ][ j ];
|
||||
var b = grid[ ip ][ j ];
|
||||
var c = grid[ ip ][ jp ];
|
||||
var d = grid[ i ][ jp ];
|
||||
|
||||
var uva = new THREE.Vector2( i / radialSegments, j / tubularSegments );
|
||||
var uvb = new THREE.Vector2( ( i + 1 ) / radialSegments, j / tubularSegments );
|
||||
var uvc = new THREE.Vector2( ( i + 1 ) / radialSegments, ( j + 1 ) / tubularSegments );
|
||||
var uvd = new THREE.Vector2( i / radialSegments, ( j + 1 ) / tubularSegments );
|
||||
|
||||
this.faces.push( new THREE.Face3( a, b, d ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );
|
||||
|
||||
this.faces.push( new THREE.Face3( b, c, d ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.computeFaceNormals();
|
||||
this.computeVertexNormals();
|
||||
|
||||
function getPos( u, in_q, in_p, radius, heightScale ) {
|
||||
|
||||
var cu = Math.cos( u );
|
||||
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 = Object.create( THREE.Geometry.prototype );
|
||||
|
|
@ -1,280 +0,0 @@
|
|||
/**
|
||||
* @author WestLangley / https://github.com/WestLangley
|
||||
* @author zz85 / https://github.com/zz85
|
||||
* @author miningold / https://github.com/miningold
|
||||
*
|
||||
* Modified from the TorusKnotGeometry by @oosmoxiecode
|
||||
*
|
||||
* Creates a tube which extrudes along a 3d spline
|
||||
*
|
||||
* Uses parallel transport frames as described in
|
||||
* http://www.cs.indiana.edu/pub/techreports/TR425.pdf
|
||||
*/
|
||||
|
||||
THREE.TubeGeometry = function ( path, segments, radius, radialSegments, closed ) {
|
||||
|
||||
THREE.Geometry.call( this );
|
||||
|
||||
this.parameters = {
|
||||
path: path,
|
||||
segments: segments,
|
||||
radius: radius,
|
||||
radialSegments: radialSegments,
|
||||
closed: closed
|
||||
};
|
||||
|
||||
segments = segments || 64;
|
||||
radius = radius || 1;
|
||||
radialSegments = radialSegments || 8;
|
||||
closed = closed || false;
|
||||
|
||||
var grid = [];
|
||||
|
||||
var scope = this,
|
||||
|
||||
tangent,
|
||||
normal,
|
||||
binormal,
|
||||
|
||||
numpoints = segments + 1,
|
||||
|
||||
x, y, z,
|
||||
tx, ty, tz,
|
||||
u, v,
|
||||
|
||||
cx, cy,
|
||||
pos, pos2 = new THREE.Vector3(),
|
||||
i, j,
|
||||
ip, jp,
|
||||
a, b, c, d,
|
||||
uva, uvb, uvc, uvd;
|
||||
|
||||
var frames = new THREE.TubeGeometry.FrenetFrames( path, segments, closed ),
|
||||
tangents = frames.tangents,
|
||||
normals = frames.normals,
|
||||
binormals = frames.binormals;
|
||||
|
||||
// proxy internals
|
||||
this.tangents = tangents;
|
||||
this.normals = normals;
|
||||
this.binormals = binormals;
|
||||
|
||||
function vert( x, y, z ) {
|
||||
|
||||
return scope.vertices.push( new THREE.Vector3( x, y, z ) ) - 1;
|
||||
|
||||
}
|
||||
|
||||
// consruct the grid
|
||||
|
||||
for ( i = 0; i < numpoints; i ++ ) {
|
||||
|
||||
grid[ i ] = [];
|
||||
|
||||
u = i / ( numpoints - 1 );
|
||||
|
||||
pos = path.getPointAt( u );
|
||||
|
||||
tangent = tangents[ i ];
|
||||
normal = normals[ i ];
|
||||
binormal = binormals[ i ];
|
||||
|
||||
for ( j = 0; j < radialSegments; j ++ ) {
|
||||
|
||||
v = j / radialSegments * 2 * Math.PI;
|
||||
|
||||
cx = - radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
|
||||
cy = radius * Math.sin( v );
|
||||
|
||||
pos2.copy( pos );
|
||||
pos2.x += cx * normal.x + cy * binormal.x;
|
||||
pos2.y += cx * normal.y + cy * binormal.y;
|
||||
pos2.z += cx * normal.z + cy * binormal.z;
|
||||
|
||||
grid[ i ][ j ] = vert( pos2.x, pos2.y, pos2.z );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// construct the mesh
|
||||
|
||||
for ( i = 0; i < segments; i ++ ) {
|
||||
|
||||
for ( j = 0; j < radialSegments; j ++ ) {
|
||||
|
||||
ip = ( closed ) ? (i + 1) % segments : i + 1;
|
||||
jp = (j + 1) % radialSegments;
|
||||
|
||||
a = grid[ i ][ j ]; // *** NOT NECESSARILY PLANAR ! ***
|
||||
b = grid[ ip ][ j ];
|
||||
c = grid[ ip ][ jp ];
|
||||
d = grid[ i ][ jp ];
|
||||
|
||||
uva = new THREE.Vector2( i / segments, j / radialSegments );
|
||||
uvb = new THREE.Vector2( ( i + 1 ) / segments, j / radialSegments );
|
||||
uvc = new THREE.Vector2( ( i + 1 ) / segments, ( j + 1 ) / radialSegments );
|
||||
uvd = new THREE.Vector2( i / segments, ( j + 1 ) / radialSegments );
|
||||
|
||||
this.faces.push( new THREE.Face3( a, b, d ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );
|
||||
|
||||
this.faces.push( new THREE.Face3( b, c, d ) );
|
||||
this.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.computeFaceNormals();
|
||||
this.computeVertexNormals();
|
||||
|
||||
};
|
||||
|
||||
THREE.TubeGeometry.prototype = Object.create( THREE.Geometry.prototype );
|
||||
|
||||
|
||||
// For computing of Frenet frames, exposing the tangents, normals and binormals the spline
|
||||
THREE.TubeGeometry.FrenetFrames = function ( path, segments, closed ) {
|
||||
|
||||
var tangent = new THREE.Vector3(),
|
||||
normal = new THREE.Vector3(),
|
||||
binormal = new THREE.Vector3(),
|
||||
|
||||
tangents = [],
|
||||
normals = [],
|
||||
binormals = [],
|
||||
|
||||
vec = new THREE.Vector3(),
|
||||
mat = new THREE.Matrix4(),
|
||||
|
||||
numpoints = segments + 1,
|
||||
theta,
|
||||
epsilon = 0.0001,
|
||||
smallest,
|
||||
|
||||
tx, ty, tz,
|
||||
i, u, v;
|
||||
|
||||
|
||||
// expose internals
|
||||
this.tangents = tangents;
|
||||
this.normals = normals;
|
||||
this.binormals = binormals;
|
||||
|
||||
// compute the tangent vectors for each segment on the path
|
||||
|
||||
for ( i = 0; i < numpoints; i ++ ) {
|
||||
|
||||
u = i / ( numpoints - 1 );
|
||||
|
||||
tangents[ i ] = path.getTangentAt( u );
|
||||
tangents[ i ].normalize();
|
||||
|
||||
}
|
||||
|
||||
initialNormal3();
|
||||
|
||||
/*
|
||||
function initialNormal1(lastBinormal) {
|
||||
// fixed start binormal. Has dangers of 0 vectors
|
||||
normals[ 0 ] = new THREE.Vector3();
|
||||
binormals[ 0 ] = new THREE.Vector3();
|
||||
if (lastBinormal===undefined) lastBinormal = new THREE.Vector3( 0, 0, 1 );
|
||||
normals[ 0 ].crossVectors( lastBinormal, tangents[ 0 ] ).normalize();
|
||||
binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ).normalize();
|
||||
}
|
||||
|
||||
function initialNormal2() {
|
||||
|
||||
// This uses the Frenet-Serret formula for deriving binormal
|
||||
var t2 = path.getTangentAt( epsilon );
|
||||
|
||||
normals[ 0 ] = new THREE.Vector3().subVectors( t2, tangents[ 0 ] ).normalize();
|
||||
binormals[ 0 ] = new THREE.Vector3().crossVectors( tangents[ 0 ], normals[ 0 ] );
|
||||
|
||||
normals[ 0 ].crossVectors( binormals[ 0 ], tangents[ 0 ] ).normalize(); // last binormal x tangent
|
||||
binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ).normalize();
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
function initialNormal3() {
|
||||
// select an initial normal vector perpenicular to the first tangent vector,
|
||||
// and in the direction of the smallest tangent xyz component
|
||||
|
||||
normals[ 0 ] = new THREE.Vector3();
|
||||
binormals[ 0 ] = new THREE.Vector3();
|
||||
smallest = Number.MAX_VALUE;
|
||||
tx = Math.abs( tangents[ 0 ].x );
|
||||
ty = Math.abs( tangents[ 0 ].y );
|
||||
tz = Math.abs( tangents[ 0 ].z );
|
||||
|
||||
if ( tx <= smallest ) {
|
||||
smallest = tx;
|
||||
normal.set( 1, 0, 0 );
|
||||
}
|
||||
|
||||
if ( ty <= smallest ) {
|
||||
smallest = ty;
|
||||
normal.set( 0, 1, 0 );
|
||||
}
|
||||
|
||||
if ( tz <= smallest ) {
|
||||
normal.set( 0, 0, 1 );
|
||||
}
|
||||
|
||||
vec.crossVectors( tangents[ 0 ], normal ).normalize();
|
||||
|
||||
normals[ 0 ].crossVectors( tangents[ 0 ], vec );
|
||||
binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
|
||||
}
|
||||
|
||||
|
||||
// compute the slowly-varying normal and binormal vectors for each segment on the path
|
||||
|
||||
for ( i = 1; i < numpoints; i ++ ) {
|
||||
|
||||
normals[ i ] = normals[ i-1 ].clone();
|
||||
|
||||
binormals[ i ] = binormals[ i-1 ].clone();
|
||||
|
||||
vec.crossVectors( tangents[ i-1 ], tangents[ i ] );
|
||||
|
||||
if ( vec.length() > epsilon ) {
|
||||
|
||||
vec.normalize();
|
||||
|
||||
theta = Math.acos( THREE.Math.clamp( tangents[ i-1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
|
||||
|
||||
normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
|
||||
|
||||
}
|
||||
|
||||
binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
|
||||
|
||||
if ( closed ) {
|
||||
|
||||
theta = Math.acos( THREE.Math.clamp( normals[ 0 ].dot( normals[ numpoints-1 ] ), - 1, 1 ) );
|
||||
theta /= ( numpoints - 1 );
|
||||
|
||||
if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ numpoints-1 ] ) ) > 0 ) {
|
||||
|
||||
theta = - theta;
|
||||
|
||||
}
|
||||
|
||||
for ( i = 1; i < numpoints; i ++ ) {
|
||||
|
||||
// twist a little...
|
||||
normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
|
||||
binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
/**
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
* @author zz85 / http://github.com/zz85
|
||||
* @author bhouston / http://exocortex.com
|
||||
*
|
||||
* Creates an arrow for visualizing directions
|
||||
*
|
||||
* Parameters:
|
||||
* dir - Vector3
|
||||
* origin - Vector3
|
||||
* length - Number
|
||||
* color - color in hex value
|
||||
* headLength - Number
|
||||
* headWidth - Number
|
||||
*/
|
||||
|
||||
THREE.ArrowHelper = ( function () {
|
||||
|
||||
var lineGeometry = new THREE.Geometry();
|
||||
lineGeometry.vertices.push( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) );
|
||||
|
||||
var coneGeometry = new THREE.CylinderGeometry( 0, 0.5, 1, 5, 1 );
|
||||
coneGeometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0, - 0.5, 0 ) );
|
||||
|
||||
return function ( dir, origin, length, color, headLength, headWidth ) {
|
||||
|
||||
// dir is assumed to be normalized
|
||||
|
||||
THREE.Object3D.call( this );
|
||||
|
||||
if ( color === undefined ) color = 0xffff00;
|
||||
if ( length === undefined ) length = 1;
|
||||
if ( headLength === undefined ) headLength = 0.2 * length;
|
||||
if ( headWidth === undefined ) headWidth = 0.2 * headLength;
|
||||
|
||||
this.position.copy( origin );
|
||||
|
||||
this.line = new THREE.Segment( lineGeometry, new THREE.LineBasicMaterial( { color: color } ) );
|
||||
this.line.matrixAutoUpdate = false;
|
||||
this.add( this.line );
|
||||
|
||||
this.cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color: color } ) );
|
||||
this.cone.matrixAutoUpdate = false;
|
||||
this.add( this.cone );
|
||||
|
||||
this.setDirection( dir );
|
||||
this.setLength( length, headLength, headWidth );
|
||||
|
||||
}
|
||||
|
||||
}() );
|
||||
|
||||
THREE.ArrowHelper.prototype = Object.create( THREE.Object3D.prototype );
|
||||
|
||||
THREE.ArrowHelper.prototype.setDirection = ( function () {
|
||||
|
||||
var axis = new THREE.Vector3();
|
||||
var radians;
|
||||
|
||||
return function ( dir ) {
|
||||
|
||||
// dir is assumed to be normalized
|
||||
|
||||
if ( dir.y > 0.99999 ) {
|
||||
|
||||
this.quaternion.set( 0, 0, 0, 1 );
|
||||
|
||||
} else if ( dir.y < - 0.99999 ) {
|
||||
|
||||
this.quaternion.set( 1, 0, 0, 0 );
|
||||
|
||||
} else {
|
||||
|
||||
axis.set( dir.z, 0, - dir.x ).normalize();
|
||||
|
||||
radians = Math.acos( dir.y );
|
||||
|
||||
this.quaternion.setFromAxisAngle( axis, radians );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}() );
|
||||
|
||||
THREE.ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {
|
||||
|
||||
if ( headLength === undefined ) headLength = 0.2 * length;
|
||||
if ( headWidth === undefined ) headWidth = 0.2 * headLength;
|
||||
|
||||
this.line.scale.set( 1, length, 1 );
|
||||
this.line.updateMatrix();
|
||||
|
||||
this.cone.scale.set( headWidth, headLength, headWidth );
|
||||
this.cone.position.y = length;
|
||||
this.cone.updateMatrix();
|
||||
|
||||
};
|
||||
|
||||
THREE.ArrowHelper.prototype.setColor = function ( color ) {
|
||||
|
||||
this.line.material.color.set( color );
|
||||
this.cone.material.color.set( color );
|
||||
|
||||
};
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
/**
|
||||
* @author sroucheray / http://sroucheray.org/
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.AxisHelper = function ( size ) {
|
||||
|
||||
size = size || 1;
|
||||
|
||||
var vertices = new Float32Array( [
|
||||
0, 0, 0, size, 0, 0,
|
||||
0, 0, 0, 0, size, 0,
|
||||
0, 0, 0, 0, 0, size
|
||||
] );
|
||||
|
||||
var colors = new Float32Array( [
|
||||
1, 0, 0, 1, 0.6, 0,
|
||||
0, 1, 0, 0.6, 1, 0,
|
||||
0, 0, 1, 0, 0.6, 1
|
||||
] );
|
||||
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
|
||||
geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
|
||||
|
||||
var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
|
||||
|
||||
THREE.Segment.call( this, geometry, material, THREE.LinePieces );
|
||||
|
||||
};
|
||||
|
||||
THREE.AxisHelper.prototype = Object.create( THREE.Segment.prototype );
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
/**
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
*/
|
||||
|
||||
// a helper to show the world-axis-aligned bounding box for an object
|
||||
|
||||
THREE.BoundingBoxHelper = function ( object, hex ) {
|
||||
|
||||
var color = ( hex !== undefined ) ? hex : 0x888888;
|
||||
|
||||
this.object = object;
|
||||
|
||||
this.box = new THREE.Box3();
|
||||
|
||||
THREE.Mesh.call( this, new THREE.BoxGeometry( 1, 1, 1 ), new THREE.MeshBasicMaterial( { color: color, wireframe: true } ) );
|
||||
|
||||
};
|
||||
|
||||
THREE.BoundingBoxHelper.prototype = Object.create( THREE.Mesh.prototype );
|
||||
|
||||
THREE.BoundingBoxHelper.prototype.update = function () {
|
||||
|
||||
this.box.setFromObject( this.object );
|
||||
|
||||
this.box.size( this.scale );
|
||||
|
||||
this.box.center( this.position );
|
||||
|
||||
};
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.BoxHelper = function ( object ) {
|
||||
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
geometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( 72 ), 3 ) );
|
||||
|
||||
THREE.Segment.call( this, geometry, new THREE.LineBasicMaterial( { color: 0xffff00 } ), THREE.LinePieces );
|
||||
|
||||
if ( object !== undefined ) {
|
||||
|
||||
this.update( object );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.BoxHelper.prototype = Object.create( THREE.Segment.prototype );
|
||||
|
||||
THREE.BoxHelper.prototype.update = function ( object ) {
|
||||
|
||||
var geometry = object.geometry;
|
||||
|
||||
if ( geometry.boundingBox === null ) {
|
||||
|
||||
geometry.computeBoundingBox();
|
||||
|
||||
}
|
||||
|
||||
var min = geometry.boundingBox.min;
|
||||
var max = geometry.boundingBox.max;
|
||||
|
||||
/*
|
||||
5____4
|
||||
1/___0/|
|
||||
| 6__|_7
|
||||
2/___3/
|
||||
|
||||
0: max.x, max.y, max.z
|
||||
1: min.x, max.y, max.z
|
||||
2: min.x, min.y, max.z
|
||||
3: max.x, min.y, max.z
|
||||
4: max.x, max.y, min.z
|
||||
5: min.x, max.y, min.z
|
||||
6: min.x, min.y, min.z
|
||||
7: max.x, min.y, min.z
|
||||
*/
|
||||
|
||||
var vertices = this.geometry.attributes.position.array;
|
||||
|
||||
vertices[ 0 ] = max.x; vertices[ 1 ] = max.y; vertices[ 2 ] = max.z;
|
||||
vertices[ 3 ] = min.x; vertices[ 4 ] = max.y; vertices[ 5 ] = max.z;
|
||||
|
||||
vertices[ 6 ] = min.x; vertices[ 7 ] = max.y; vertices[ 8 ] = max.z;
|
||||
vertices[ 9 ] = min.x; vertices[ 10 ] = min.y; vertices[ 11 ] = max.z;
|
||||
|
||||
vertices[ 12 ] = min.x; vertices[ 13 ] = min.y; vertices[ 14 ] = max.z;
|
||||
vertices[ 15 ] = max.x; vertices[ 16 ] = min.y; vertices[ 17 ] = max.z;
|
||||
|
||||
vertices[ 18 ] = max.x; vertices[ 19 ] = min.y; vertices[ 20 ] = max.z;
|
||||
vertices[ 21 ] = max.x; vertices[ 22 ] = max.y; vertices[ 23 ] = max.z;
|
||||
|
||||
//
|
||||
|
||||
vertices[ 24 ] = max.x; vertices[ 25 ] = max.y; vertices[ 26 ] = min.z;
|
||||
vertices[ 27 ] = min.x; vertices[ 28 ] = max.y; vertices[ 29 ] = min.z;
|
||||
|
||||
vertices[ 30 ] = min.x; vertices[ 31 ] = max.y; vertices[ 32 ] = min.z;
|
||||
vertices[ 33 ] = min.x; vertices[ 34 ] = min.y; vertices[ 35 ] = min.z;
|
||||
|
||||
vertices[ 36 ] = min.x; vertices[ 37 ] = min.y; vertices[ 38 ] = min.z;
|
||||
vertices[ 39 ] = max.x; vertices[ 40 ] = min.y; vertices[ 41 ] = min.z;
|
||||
|
||||
vertices[ 42 ] = max.x; vertices[ 43 ] = min.y; vertices[ 44 ] = min.z;
|
||||
vertices[ 45 ] = max.x; vertices[ 46 ] = max.y; vertices[ 47 ] = min.z;
|
||||
|
||||
//
|
||||
|
||||
vertices[ 48 ] = max.x; vertices[ 49 ] = max.y; vertices[ 50 ] = max.z;
|
||||
vertices[ 51 ] = max.x; vertices[ 52 ] = max.y; vertices[ 53 ] = min.z;
|
||||
|
||||
vertices[ 54 ] = min.x; vertices[ 55 ] = max.y; vertices[ 56 ] = max.z;
|
||||
vertices[ 57 ] = min.x; vertices[ 58 ] = max.y; vertices[ 59 ] = min.z;
|
||||
|
||||
vertices[ 60 ] = min.x; vertices[ 61 ] = min.y; vertices[ 62 ] = max.z;
|
||||
vertices[ 63 ] = min.x; vertices[ 64 ] = min.y; vertices[ 65 ] = min.z;
|
||||
|
||||
vertices[ 66 ] = max.x; vertices[ 67 ] = min.y; vertices[ 68 ] = max.z;
|
||||
vertices[ 69 ] = max.x; vertices[ 70 ] = min.y; vertices[ 71 ] = min.z;
|
||||
|
||||
this.geometry.attributes.position.needsUpdate = true;
|
||||
|
||||
this.geometry.computeBoundingSphere();
|
||||
|
||||
this.matrixAutoUpdate = false;
|
||||
this.matrixWorld = object.matrixWorld;
|
||||
|
||||
};
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*
|
||||
* - shows frustum, line of sight and up of the camera
|
||||
* - suitable for fast updates
|
||||
* - based on frustum visualization in lightgl.js shadowmap example
|
||||
* http://evanw.github.com/lightgl.js/tests/shadowmap.html
|
||||
*/
|
||||
|
||||
THREE.CameraHelper = function ( camera ) {
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
var material = new THREE.LineBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors } );
|
||||
|
||||
var pointMap = {};
|
||||
|
||||
// colors
|
||||
|
||||
var hexFrustum = 0xffaa00;
|
||||
var hexCone = 0xff0000;
|
||||
var hexUp = 0x00aaff;
|
||||
var hexTarget = 0xffffff;
|
||||
var hexCross = 0x333333;
|
||||
|
||||
// near
|
||||
|
||||
addLine( "n1", "n2", hexFrustum );
|
||||
addLine( "n2", "n4", hexFrustum );
|
||||
addLine( "n4", "n3", hexFrustum );
|
||||
addLine( "n3", "n1", hexFrustum );
|
||||
|
||||
// far
|
||||
|
||||
addLine( "f1", "f2", hexFrustum );
|
||||
addLine( "f2", "f4", hexFrustum );
|
||||
addLine( "f4", "f3", hexFrustum );
|
||||
addLine( "f3", "f1", hexFrustum );
|
||||
|
||||
// sides
|
||||
|
||||
addLine( "n1", "f1", hexFrustum );
|
||||
addLine( "n2", "f2", hexFrustum );
|
||||
addLine( "n3", "f3", hexFrustum );
|
||||
addLine( "n4", "f4", hexFrustum );
|
||||
|
||||
// cone
|
||||
|
||||
addLine( "p", "n1", hexCone );
|
||||
addLine( "p", "n2", hexCone );
|
||||
addLine( "p", "n3", hexCone );
|
||||
addLine( "p", "n4", hexCone );
|
||||
|
||||
// up
|
||||
|
||||
addLine( "u1", "u2", hexUp );
|
||||
addLine( "u2", "u3", hexUp );
|
||||
addLine( "u3", "u1", hexUp );
|
||||
|
||||
// target
|
||||
|
||||
addLine( "c", "t", hexTarget );
|
||||
addLine( "p", "c", hexCross );
|
||||
|
||||
// cross
|
||||
|
||||
addLine( "cn1", "cn2", hexCross );
|
||||
addLine( "cn3", "cn4", hexCross );
|
||||
|
||||
addLine( "cf1", "cf2", hexCross );
|
||||
addLine( "cf3", "cf4", hexCross );
|
||||
|
||||
function addLine( a, b, hex ) {
|
||||
|
||||
addPoint( a, hex );
|
||||
addPoint( b, hex );
|
||||
|
||||
}
|
||||
|
||||
function addPoint( id, hex ) {
|
||||
|
||||
geometry.vertices.push( new THREE.Vector3() );
|
||||
geometry.colors.push( new THREE.Color( hex ) );
|
||||
|
||||
if ( pointMap[ id ] === undefined ) {
|
||||
|
||||
pointMap[ id ] = [];
|
||||
|
||||
}
|
||||
|
||||
pointMap[ id ].push( geometry.vertices.length - 1 );
|
||||
|
||||
}
|
||||
|
||||
THREE.Segment.call( this, geometry, material, THREE.LinePieces );
|
||||
|
||||
this.camera = camera;
|
||||
this.matrixWorld = camera.matrixWorld;
|
||||
this.matrixAutoUpdate = false;
|
||||
|
||||
this.pointMap = pointMap;
|
||||
|
||||
this.update();
|
||||
|
||||
};
|
||||
|
||||
THREE.CameraHelper.prototype = Object.create( THREE.Segment.prototype );
|
||||
|
||||
THREE.CameraHelper.prototype.update = function () {
|
||||
|
||||
var vector = new THREE.Vector3();
|
||||
var camera = new THREE.Camera();
|
||||
var projector = new THREE.Projector();
|
||||
|
||||
return function () {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var w = 1, h = 1;
|
||||
|
||||
// we need just camera projection matrix
|
||||
// world matrix must be identity
|
||||
|
||||
camera.projectionMatrix.copy( this.camera.projectionMatrix );
|
||||
|
||||
// center / target
|
||||
|
||||
setPoint( "c", 0, 0, - 1 );
|
||||
setPoint( "t", 0, 0, 1 );
|
||||
|
||||
// near
|
||||
|
||||
setPoint( "n1", - w, - h, - 1 );
|
||||
setPoint( "n2", w, - h, - 1 );
|
||||
setPoint( "n3", - w, h, - 1 );
|
||||
setPoint( "n4", w, h, - 1 );
|
||||
|
||||
// far
|
||||
|
||||
setPoint( "f1", - w, - h, 1 );
|
||||
setPoint( "f2", w, - h, 1 );
|
||||
setPoint( "f3", - w, h, 1 );
|
||||
setPoint( "f4", w, h, 1 );
|
||||
|
||||
// up
|
||||
|
||||
setPoint( "u1", w * 0.7, h * 1.1, - 1 );
|
||||
setPoint( "u2", - w * 0.7, h * 1.1, - 1 );
|
||||
setPoint( "u3", 0, h * 2, - 1 );
|
||||
|
||||
// cross
|
||||
|
||||
setPoint( "cf1", - w, 0, 1 );
|
||||
setPoint( "cf2", w, 0, 1 );
|
||||
setPoint( "cf3", 0, - h, 1 );
|
||||
setPoint( "cf4", 0, h, 1 );
|
||||
|
||||
setPoint( "cn1", - w, 0, - 1 );
|
||||
setPoint( "cn2", w, 0, - 1 );
|
||||
setPoint( "cn3", 0, - h, - 1 );
|
||||
setPoint( "cn4", 0, h, - 1 );
|
||||
|
||||
function setPoint( point, x, y, z ) {
|
||||
|
||||
vector.set( x, y, z );
|
||||
projector.unprojectVector( vector, camera );
|
||||
|
||||
var points = scope.pointMap[ point ];
|
||||
|
||||
if ( points !== undefined ) {
|
||||
|
||||
for ( var i = 0, il = points.length; i < il; i ++ ) {
|
||||
|
||||
scope.geometry.vertices[ points[ i ] ].copy( vector );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.geometry.verticesNeedUpdate = true;
|
||||
|
||||
};
|
||||
|
||||
}();
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
*/
|
||||
|
||||
THREE.DirectionalLightHelper = function ( light, size ) {
|
||||
|
||||
THREE.Object3D.call( this );
|
||||
|
||||
this.light = light;
|
||||
this.light.updateMatrixWorld();
|
||||
|
||||
this.matrixWorld = light.matrixWorld;
|
||||
this.matrixAutoUpdate = false;
|
||||
|
||||
size = size || 1;
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
geometry.vertices.push(
|
||||
new THREE.Vector3( - size, size, 0 ),
|
||||
new THREE.Vector3( size, size, 0 ),
|
||||
new THREE.Vector3( size, - size, 0 ),
|
||||
new THREE.Vector3( - size, - size, 0 ),
|
||||
new THREE.Vector3( - size, size, 0 )
|
||||
);
|
||||
|
||||
var material = new THREE.LineBasicMaterial( { fog: false } );
|
||||
material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
|
||||
|
||||
this.lightPlane = new THREE.Segment( geometry, material );
|
||||
this.add( this.lightPlane );
|
||||
|
||||
geometry = new THREE.Geometry();
|
||||
geometry.vertices.push(
|
||||
new THREE.Vector3(),
|
||||
new THREE.Vector3()
|
||||
);
|
||||
|
||||
material = new THREE.LineBasicMaterial( { fog: false } );
|
||||
material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
|
||||
|
||||
this.targetLine = new THREE.Segment( geometry, material );
|
||||
this.add( this.targetLine );
|
||||
|
||||
this.update();
|
||||
|
||||
};
|
||||
|
||||
THREE.DirectionalLightHelper.prototype = Object.create( THREE.Object3D.prototype );
|
||||
|
||||
THREE.DirectionalLightHelper.prototype.dispose = function () {
|
||||
|
||||
this.lightPlane.geometry.dispose();
|
||||
this.lightPlane.material.dispose();
|
||||
this.targetLine.geometry.dispose();
|
||||
this.targetLine.material.dispose();
|
||||
};
|
||||
|
||||
THREE.DirectionalLightHelper.prototype.update = function () {
|
||||
|
||||
var v1 = new THREE.Vector3();
|
||||
var v2 = new THREE.Vector3();
|
||||
var v3 = new THREE.Vector3();
|
||||
|
||||
return function () {
|
||||
|
||||
v1.setFromMatrixPosition( this.light.matrixWorld );
|
||||
v2.setFromMatrixPosition( this.light.target.matrixWorld );
|
||||
v3.subVectors( v2, v1 );
|
||||
|
||||
this.lightPlane.lookAt( v3 );
|
||||
this.lightPlane.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
|
||||
|
||||
this.targetLine.geometry.vertices[ 1 ].copy( v3 );
|
||||
this.targetLine.geometry.verticesNeedUpdate = true;
|
||||
this.targetLine.material.color.copy( this.lightPlane.material.color );
|
||||
|
||||
}
|
||||
|
||||
}();
|
||||
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
/**
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
*/
|
||||
|
||||
THREE.EdgesHelper = function ( object, hex ) {
|
||||
|
||||
var color = ( hex !== undefined ) ? hex : 0xffffff;
|
||||
|
||||
var edge = [ 0, 0 ], hash = {};
|
||||
var sortFunction = function ( a, b ) { return a - b };
|
||||
|
||||
var keys = [ 'a', 'b', 'c' ];
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
|
||||
var geometry2 = object.geometry.clone();
|
||||
|
||||
geometry2.mergeVertices();
|
||||
geometry2.computeFaceNormals();
|
||||
|
||||
var vertices = geometry2.vertices;
|
||||
var faces = geometry2.faces;
|
||||
var numEdges = 0;
|
||||
|
||||
for ( var i = 0, l = faces.length; i < l; i ++ ) {
|
||||
|
||||
var face = faces[ i ];
|
||||
|
||||
for ( var j = 0; j < 3; j ++ ) {
|
||||
|
||||
edge[ 0 ] = face[ keys[ j ] ];
|
||||
edge[ 1 ] = face[ keys[ ( j + 1 ) % 3 ] ];
|
||||
edge.sort( sortFunction );
|
||||
|
||||
var key = edge.toString();
|
||||
|
||||
if ( hash[ key ] === undefined ) {
|
||||
|
||||
hash[ key ] = { vert1: edge[ 0 ], vert2: edge[ 1 ], face1: i, face2: undefined };
|
||||
numEdges ++;
|
||||
|
||||
} else {
|
||||
|
||||
hash[ key ].face2 = i;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.addAttribute( 'position', new THREE.Float32Attribute( numEdges * 2 * 3, 3 ) );
|
||||
|
||||
var coords = geometry.attributes.position.array;
|
||||
|
||||
var index = 0;
|
||||
|
||||
for ( var key in hash ) {
|
||||
|
||||
var h = hash[ key ];
|
||||
|
||||
if ( h.face2 === undefined || faces[ h.face1 ].normal.dot( faces[ h.face2 ].normal ) < 0.9999 ) { // hardwired const OK
|
||||
|
||||
var vertex = vertices[ h.vert1 ];
|
||||
coords[ index ++ ] = vertex.x;
|
||||
coords[ index ++ ] = vertex.y;
|
||||
coords[ index ++ ] = vertex.z;
|
||||
|
||||
vertex = vertices[ h.vert2 ];
|
||||
coords[ index ++ ] = vertex.x;
|
||||
coords[ index ++ ] = vertex.y;
|
||||
coords[ index ++ ] = vertex.z;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
THREE.Segment.call( this, geometry, new THREE.LineBasicMaterial( { color: color } ), THREE.LinePieces );
|
||||
|
||||
this.matrixAutoUpdate = false;
|
||||
this.matrixWorld = object.matrixWorld;
|
||||
|
||||
};
|
||||
|
||||
THREE.EdgesHelper.prototype = Object.create( THREE.Segment.prototype );
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
*/
|
||||
|
||||
THREE.FaceNormalsHelper = function ( object, size, hex, linewidth ) {
|
||||
|
||||
this.object = object;
|
||||
|
||||
this.size = ( size !== undefined ) ? size : 1;
|
||||
|
||||
var color = ( hex !== undefined ) ? hex : 0xffff00;
|
||||
|
||||
var width = ( linewidth !== undefined ) ? linewidth : 1;
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
var faces = this.object.geometry.faces;
|
||||
|
||||
for ( var i = 0, l = faces.length; i < l; i ++ ) {
|
||||
|
||||
geometry.vertices.push( new THREE.Vector3(), new THREE.Vector3() );
|
||||
|
||||
}
|
||||
|
||||
THREE.Segment.call( this, geometry, new THREE.LineBasicMaterial( { color: color, linewidth: width } ), THREE.LinePieces );
|
||||
|
||||
this.matrixAutoUpdate = false;
|
||||
|
||||
this.normalMatrix = new THREE.Matrix3();
|
||||
|
||||
this.update();
|
||||
|
||||
};
|
||||
|
||||
THREE.FaceNormalsHelper.prototype = Object.create( THREE.Segment.prototype );
|
||||
|
||||
THREE.FaceNormalsHelper.prototype.update = function () {
|
||||
|
||||
var vertices = this.geometry.vertices;
|
||||
|
||||
var object = this.object;
|
||||
var objectVertices = object.geometry.vertices;
|
||||
var objectFaces = object.geometry.faces;
|
||||
var objectWorldMatrix = object.matrixWorld;
|
||||
|
||||
object.updateMatrixWorld( true );
|
||||
|
||||
this.normalMatrix.getNormalMatrix( objectWorldMatrix );
|
||||
|
||||
for ( var i = 0, i2 = 0, l = objectFaces.length; i < l; i ++, i2 += 2 ) {
|
||||
|
||||
var face = objectFaces[ i ];
|
||||
|
||||
vertices[ i2 ].copy( objectVertices[ face.a ] )
|
||||
.add( objectVertices[ face.b ] )
|
||||
.add( objectVertices[ face.c ] )
|
||||
.divideScalar( 3 )
|
||||
.applyMatrix4( objectWorldMatrix );
|
||||
|
||||
vertices[ i2 + 1 ].copy( face.normal )
|
||||
.applyMatrix3( this.normalMatrix )
|
||||
.normalize()
|
||||
.multiplyScalar( this.size )
|
||||
.add( vertices[ i2 ] );
|
||||
|
||||
}
|
||||
|
||||
this.geometry.verticesNeedUpdate = true;
|
||||
|
||||
return this;
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.GridHelper = function ( size, step ) {
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
|
||||
|
||||
this.color1 = new THREE.Color( 0x444444 );
|
||||
this.color2 = new THREE.Color( 0x888888 );
|
||||
|
||||
for ( var i = - size; i <= size; i += step ) {
|
||||
|
||||
geometry.vertices.push(
|
||||
new THREE.Vector3( - size, 0, i ), new THREE.Vector3( size, 0, i ),
|
||||
new THREE.Vector3( i, 0, - size ), new THREE.Vector3( i, 0, size )
|
||||
);
|
||||
|
||||
var color = i === 0 ? this.color1 : this.color2;
|
||||
|
||||
geometry.colors.push( color, color, color, color );
|
||||
|
||||
}
|
||||
|
||||
THREE.Segment.call( this, geometry, material, THREE.LinePieces );
|
||||
|
||||
};
|
||||
|
||||
THREE.GridHelper.prototype = Object.create( THREE.Segment.prototype );
|
||||
|
||||
THREE.GridHelper.prototype.setColors = function( colorCenterLine, colorGrid ) {
|
||||
|
||||
this.color1.set( colorCenterLine );
|
||||
this.color2.set( colorGrid );
|
||||
|
||||
this.geometry.colorsNeedUpdate = true;
|
||||
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.HemisphereLightHelper = function ( light, sphereSize, arrowLength, domeSize ) {
|
||||
|
||||
THREE.Object3D.call( this );
|
||||
|
||||
this.light = light;
|
||||
this.light.updateMatrixWorld();
|
||||
|
||||
this.matrixWorld = light.matrixWorld;
|
||||
this.matrixAutoUpdate = false;
|
||||
|
||||
this.colors = [ new THREE.Color(), new THREE.Color() ];
|
||||
|
||||
var geometry = new THREE.SphereGeometry( sphereSize, 4, 2 );
|
||||
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
|
||||
|
||||
for ( var i = 0, il = 8; i < il; i ++ ) {
|
||||
|
||||
geometry.faces[ i ].color = this.colors[ i < 4 ? 0 : 1 ];
|
||||
|
||||
}
|
||||
|
||||
var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, wireframe: true } );
|
||||
|
||||
this.lightSphere = new THREE.Mesh( geometry, material );
|
||||
this.add( this.lightSphere );
|
||||
|
||||
this.update();
|
||||
|
||||
};
|
||||
|
||||
THREE.HemisphereLightHelper.prototype = Object.create( THREE.Object3D.prototype );
|
||||
|
||||
THREE.HemisphereLightHelper.prototype.dispose = function () {
|
||||
this.lightSphere.geometry.dispose();
|
||||
this.lightSphere.material.dispose();
|
||||
};
|
||||
|
||||
THREE.HemisphereLightHelper.prototype.update = function () {
|
||||
|
||||
var vector = new THREE.Vector3();
|
||||
|
||||
return function () {
|
||||
|
||||
this.colors[ 0 ].copy( this.light.color ).multiplyScalar( this.light.intensity );
|
||||
this.colors[ 1 ].copy( this.light.groundColor ).multiplyScalar( this.light.intensity );
|
||||
|
||||
this.lightSphere.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() );
|
||||
this.lightSphere.geometry.colorsNeedUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
}();
|
||||
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.PointLightHelper = function ( light, sphereSize ) {
|
||||
|
||||
this.light = light;
|
||||
this.light.updateMatrixWorld();
|
||||
|
||||
var geometry = new THREE.SphereGeometry( sphereSize, 4, 2 );
|
||||
var material = new THREE.MeshBasicMaterial( { wireframe: true, fog: false } );
|
||||
material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
|
||||
|
||||
THREE.Mesh.call( this, geometry, material );
|
||||
|
||||
this.matrixWorld = this.light.matrixWorld;
|
||||
this.matrixAutoUpdate = false;
|
||||
|
||||
/*
|
||||
var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
|
||||
var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
|
||||
|
||||
this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
|
||||
this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
|
||||
|
||||
var d = light.distance;
|
||||
|
||||
if ( d === 0.0 ) {
|
||||
|
||||
this.lightDistance.visible = false;
|
||||
|
||||
} else {
|
||||
|
||||
this.lightDistance.scale.set( d, d, d );
|
||||
|
||||
}
|
||||
|
||||
this.add( this.lightDistance );
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
THREE.PointLightHelper.prototype = Object.create( THREE.Mesh.prototype );
|
||||
|
||||
THREE.PointLightHelper.prototype.dispose = function () {
|
||||
|
||||
this.geometry.dispose();
|
||||
this.material.dispose();
|
||||
};
|
||||
|
||||
THREE.PointLightHelper.prototype.update = function () {
|
||||
|
||||
this.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
|
||||
|
||||
/*
|
||||
var d = this.light.distance;
|
||||
|
||||
if ( d === 0.0 ) {
|
||||
|
||||
this.lightDistance.visible = false;
|
||||
|
||||
} else {
|
||||
|
||||
this.lightDistance.visible = true;
|
||||
this.lightDistance.scale.set( d, d, d );
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
/**
|
||||
* @author Sean Griffin / http://twitter.com/sgrif
|
||||
* @author Michael Guerrero / http://realitymeltdown.com
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author ikerr / http://verold.com
|
||||
*/
|
||||
|
||||
THREE.SkeletonHelper = function ( object ) {
|
||||
|
||||
this.bones = this.getBoneList( object );
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
for ( var i = 0; i < this.bones.length; i ++ ) {
|
||||
|
||||
var bone = this.bones[ i ];
|
||||
|
||||
if ( bone.parent instanceof THREE.Bone ) {
|
||||
|
||||
geometry.vertices.push( new THREE.Vector3() );
|
||||
geometry.vertices.push( new THREE.Vector3() );
|
||||
geometry.colors.push( new THREE.Color( 0, 0, 1 ) );
|
||||
geometry.colors.push( new THREE.Color( 0, 1, 0 ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors, depthTest: false, depthWrite: false, transparent: true } );
|
||||
|
||||
THREE.Segment.call( this, geometry, material, THREE.LinePieces );
|
||||
|
||||
this.root = object;
|
||||
|
||||
this.matrixWorld = object.matrixWorld;
|
||||
this.matrixAutoUpdate = false;
|
||||
|
||||
this.update();
|
||||
|
||||
};
|
||||
|
||||
|
||||
THREE.SkeletonHelper.prototype = Object.create( THREE.Segment.prototype );
|
||||
|
||||
THREE.SkeletonHelper.prototype.getBoneList = function( object ) {
|
||||
|
||||
var boneList = [];
|
||||
|
||||
if ( object instanceof THREE.Bone ) {
|
||||
|
||||
boneList.push( object );
|
||||
|
||||
}
|
||||
|
||||
for ( var i = 0; i < object.children.length; i ++ ) {
|
||||
|
||||
boneList.push.apply( boneList, this.getBoneList( object.children[ i ] ) );
|
||||
|
||||
}
|
||||
|
||||
return boneList;
|
||||
|
||||
};
|
||||
|
||||
THREE.SkeletonHelper.prototype.update = function () {
|
||||
|
||||
var geometry = this.geometry;
|
||||
|
||||
var matrixWorldInv = new THREE.Matrix4().getInverse( this.root.matrixWorld );
|
||||
|
||||
var boneMatrix = new THREE.Matrix4();
|
||||
|
||||
var j = 0;
|
||||
|
||||
for ( var i = 0; i < this.bones.length; i ++ ) {
|
||||
|
||||
var bone = this.bones[ i ];
|
||||
|
||||
if ( bone.parent instanceof THREE.Bone ) {
|
||||
|
||||
boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld );
|
||||
geometry.vertices[ j ].setFromMatrixPosition( boneMatrix );
|
||||
|
||||
boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld );
|
||||
geometry.vertices[ j + 1 ].setFromMatrixPosition( boneMatrix );
|
||||
|
||||
j += 2;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.verticesNeedUpdate = true;
|
||||
|
||||
geometry.computeBoundingSphere();
|
||||
|
||||
};
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
*/
|
||||
|
||||
THREE.SpotLightHelper = function ( light ) {
|
||||
|
||||
THREE.Object3D.call( this );
|
||||
|
||||
this.light = light;
|
||||
this.light.updateMatrixWorld();
|
||||
|
||||
this.matrixWorld = light.matrixWorld;
|
||||
this.matrixAutoUpdate = false;
|
||||
|
||||
var geometry = new THREE.CylinderGeometry( 0, 1, 1, 8, 1, true );
|
||||
|
||||
geometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0, - 0.5, 0 ) );
|
||||
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
|
||||
|
||||
var material = new THREE.MeshBasicMaterial( { wireframe: true, fog: false } );
|
||||
|
||||
this.cone = new THREE.Mesh( geometry, material );
|
||||
this.add( this.cone );
|
||||
|
||||
this.update();
|
||||
|
||||
};
|
||||
|
||||
THREE.SpotLightHelper.prototype = Object.create( THREE.Object3D.prototype );
|
||||
|
||||
THREE.SpotLightHelper.prototype.dispose = function () {
|
||||
this.cone.geometry.dispose();
|
||||
this.cone.material.dispose();
|
||||
};
|
||||
|
||||
THREE.SpotLightHelper.prototype.update = function () {
|
||||
|
||||
var vector = new THREE.Vector3();
|
||||
var vector2 = new THREE.Vector3();
|
||||
|
||||
return function () {
|
||||
|
||||
var coneLength = this.light.distance ? this.light.distance : 10000;
|
||||
var coneWidth = coneLength * Math.tan( this.light.angle );
|
||||
|
||||
this.cone.scale.set( coneWidth, coneWidth, coneLength );
|
||||
|
||||
vector.setFromMatrixPosition( this.light.matrixWorld );
|
||||
vector2.setFromMatrixPosition( this.light.target.matrixWorld );
|
||||
|
||||
this.cone.lookAt( vector2.sub( vector ) );
|
||||
|
||||
this.cone.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
|
||||
|
||||
};
|
||||
|
||||
}();
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
*/
|
||||
|
||||
THREE.VertexNormalsHelper = function ( object, size, hex, linewidth ) {
|
||||
|
||||
this.object = object;
|
||||
|
||||
this.size = ( size !== undefined ) ? size : 1;
|
||||
|
||||
var color = ( hex !== undefined ) ? hex : 0xff0000;
|
||||
|
||||
var width = ( linewidth !== undefined ) ? linewidth : 1;
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
var vertices = object.geometry.vertices;
|
||||
|
||||
var faces = object.geometry.faces;
|
||||
|
||||
for ( var i = 0, l = faces.length; i < l; i ++ ) {
|
||||
|
||||
var face = faces[ i ];
|
||||
|
||||
for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
|
||||
|
||||
geometry.vertices.push( new THREE.Vector3(), new THREE.Vector3() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
THREE.Segment.call( this, geometry, new THREE.LineBasicMaterial( { color: color, linewidth: width } ), THREE.LinePieces );
|
||||
|
||||
this.matrixAutoUpdate = false;
|
||||
|
||||
this.normalMatrix = new THREE.Matrix3();
|
||||
|
||||
this.update();
|
||||
|
||||
};
|
||||
|
||||
THREE.VertexNormalsHelper.prototype = Object.create( THREE.Segment.prototype );
|
||||
|
||||
THREE.VertexNormalsHelper.prototype.update = ( function ( object ) {
|
||||
|
||||
var v1 = new THREE.Vector3();
|
||||
|
||||
return function( object ) {
|
||||
|
||||
var keys = [ 'a', 'b', 'c', 'd' ];
|
||||
|
||||
this.object.updateMatrixWorld( true );
|
||||
|
||||
this.normalMatrix.getNormalMatrix( this.object.matrixWorld );
|
||||
|
||||
var vertices = this.geometry.vertices;
|
||||
|
||||
var verts = this.object.geometry.vertices;
|
||||
|
||||
var faces = this.object.geometry.faces;
|
||||
|
||||
var worldMatrix = this.object.matrixWorld;
|
||||
|
||||
var idx = 0;
|
||||
|
||||
for ( var i = 0, l = faces.length; i < l; i ++ ) {
|
||||
|
||||
var face = faces[ i ];
|
||||
|
||||
for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
|
||||
|
||||
var vertexId = face[ keys[ j ] ];
|
||||
var vertex = verts[ vertexId ];
|
||||
|
||||
var normal = face.vertexNormals[ j ];
|
||||
|
||||
vertices[ idx ].copy( vertex ).applyMatrix4( worldMatrix );
|
||||
|
||||
v1.copy( normal ).applyMatrix3( this.normalMatrix ).normalize().multiplyScalar( this.size );
|
||||
|
||||
v1.add( vertices[ idx ] );
|
||||
idx = idx + 1;
|
||||
|
||||
vertices[ idx ].copy( v1 );
|
||||
idx = idx + 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.geometry.verticesNeedUpdate = true;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}());
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
*/
|
||||
|
||||
THREE.VertexTangentsHelper = function ( object, size, hex, linewidth ) {
|
||||
|
||||
this.object = object;
|
||||
|
||||
this.size = ( size !== undefined ) ? size : 1;
|
||||
|
||||
var color = ( hex !== undefined ) ? hex : 0x0000ff;
|
||||
|
||||
var width = ( linewidth !== undefined ) ? linewidth : 1;
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
var vertices = object.geometry.vertices;
|
||||
|
||||
var faces = object.geometry.faces;
|
||||
|
||||
for ( var i = 0, l = faces.length; i < l; i ++ ) {
|
||||
|
||||
var face = faces[ i ];
|
||||
|
||||
for ( var j = 0, jl = face.vertexTangents.length; j < jl; j ++ ) {
|
||||
|
||||
geometry.vertices.push( new THREE.Vector3() );
|
||||
geometry.vertices.push( new THREE.Vector3() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
THREE.Segment.call( this, geometry, new THREE.LineBasicMaterial( { color: color, linewidth: width } ), THREE.LinePieces );
|
||||
|
||||
this.matrixAutoUpdate = false;
|
||||
|
||||
this.update();
|
||||
|
||||
};
|
||||
|
||||
THREE.VertexTangentsHelper.prototype = Object.create( THREE.Segment.prototype );
|
||||
|
||||
THREE.VertexTangentsHelper.prototype.update = ( function ( object ) {
|
||||
|
||||
var v1 = new THREE.Vector3();
|
||||
|
||||
return function( object ) {
|
||||
|
||||
var keys = [ 'a', 'b', 'c', 'd' ];
|
||||
|
||||
this.object.updateMatrixWorld( true );
|
||||
|
||||
var vertices = this.geometry.vertices;
|
||||
|
||||
var verts = this.object.geometry.vertices;
|
||||
|
||||
var faces = this.object.geometry.faces;
|
||||
|
||||
var worldMatrix = this.object.matrixWorld;
|
||||
|
||||
var idx = 0;
|
||||
|
||||
for ( var i = 0, l = faces.length; i < l; i ++ ) {
|
||||
|
||||
var face = faces[ i ];
|
||||
|
||||
for ( var j = 0, jl = face.vertexTangents.length; j < jl; j ++ ) {
|
||||
|
||||
var vertexId = face[ keys[ j ] ];
|
||||
var vertex = verts[ vertexId ];
|
||||
|
||||
var tangent = face.vertexTangents[ j ];
|
||||
|
||||
vertices[ idx ].copy( vertex ).applyMatrix4( worldMatrix );
|
||||
|
||||
v1.copy( tangent ).transformDirection( worldMatrix ).multiplyScalar( this.size );
|
||||
|
||||
v1.add( vertices[ idx ] );
|
||||
idx = idx + 1;
|
||||
|
||||
vertices[ idx ].copy( v1 );
|
||||
idx = idx + 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.geometry.verticesNeedUpdate = true;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}());
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.WireframeHelper = function ( object, hex ) {
|
||||
|
||||
var color = ( hex !== undefined ) ? hex : 0xffffff;
|
||||
|
||||
var edge = [ 0, 0 ], hash = {};
|
||||
var sortFunction = function ( a, b ) { return a - b };
|
||||
|
||||
var keys = [ 'a', 'b', 'c' ];
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
|
||||
if ( object.geometry instanceof THREE.Geometry ) {
|
||||
|
||||
var vertices = object.geometry.vertices;
|
||||
var faces = object.geometry.faces;
|
||||
var numEdges = 0;
|
||||
|
||||
// allocate maximal size
|
||||
var edges = new Uint32Array( 6 * faces.length );
|
||||
|
||||
for ( var i = 0, l = faces.length; i < l; i ++ ) {
|
||||
|
||||
var face = faces[ i ];
|
||||
|
||||
for ( var j = 0; j < 3; j ++ ) {
|
||||
|
||||
edge[ 0 ] = face[ keys[ j ] ];
|
||||
edge[ 1 ] = face[ keys[ ( j + 1 ) % 3 ] ];
|
||||
edge.sort( sortFunction );
|
||||
|
||||
var key = edge.toString();
|
||||
|
||||
if ( hash[ key ] === undefined ) {
|
||||
|
||||
edges[ 2 * numEdges ] = edge[ 0 ];
|
||||
edges[ 2 * numEdges + 1 ] = edge[ 1 ];
|
||||
hash[ key ] = true;
|
||||
numEdges ++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var coords = new Float32Array( numEdges * 2 * 3 );
|
||||
|
||||
for ( var i = 0, l = numEdges; i < l; i ++ ) {
|
||||
|
||||
for ( var j = 0; j < 2; j ++ ) {
|
||||
|
||||
var vertex = vertices[ edges [ 2 * i + j] ];
|
||||
|
||||
var index = 6 * i + 3 * j;
|
||||
coords[ index + 0 ] = vertex.x;
|
||||
coords[ index + 1 ] = vertex.y;
|
||||
coords[ index + 2 ] = vertex.z;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
|
||||
|
||||
} else if ( object.geometry instanceof THREE.BufferGeometry ) {
|
||||
|
||||
if ( object.geometry.attributes.index !== undefined ) { // Indexed BufferGeometry
|
||||
|
||||
var vertices = object.geometry.attributes.position.array;
|
||||
var indices = object.geometry.attributes.index.array;
|
||||
var offsets = object.geometry.offsets;
|
||||
var numEdges = 0;
|
||||
|
||||
// allocate maximal size
|
||||
var edges = new Uint32Array( 2 * indices.length );
|
||||
|
||||
for ( var o = 0, ol = offsets.length; o < ol; ++ o ) {
|
||||
|
||||
var start = offsets[ o ].start;
|
||||
var count = offsets[ o ].count;
|
||||
var index = offsets[ o ].index;
|
||||
|
||||
for ( var i = start, il = start + count; i < il; i += 3 ) {
|
||||
|
||||
for ( var j = 0; j < 3; j ++ ) {
|
||||
|
||||
edge[ 0 ] = index + indices[ i + j ];
|
||||
edge[ 1 ] = index + indices[ i + ( j + 1 ) % 3 ];
|
||||
edge.sort( sortFunction );
|
||||
|
||||
var key = edge.toString();
|
||||
|
||||
if ( hash[ key ] === undefined ) {
|
||||
|
||||
edges[ 2 * numEdges ] = edge[ 0 ];
|
||||
edges[ 2 * numEdges + 1 ] = edge[ 1 ];
|
||||
hash[ key ] = true;
|
||||
numEdges ++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var coords = new Float32Array( numEdges * 2 * 3 );
|
||||
|
||||
for ( var i = 0, l = numEdges; i < l; i ++ ) {
|
||||
|
||||
for ( var j = 0; j < 2; j ++ ) {
|
||||
|
||||
var index = 6 * i + 3 * j;
|
||||
var index2 = 3 * edges[ 2 * i + j];
|
||||
coords[ index + 0 ] = vertices[ index2 ];
|
||||
coords[ index + 1 ] = vertices[ index2 + 1 ];
|
||||
coords[ index + 2 ] = vertices[ index2 + 2 ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
|
||||
|
||||
} else { // non-indexed BufferGeometry
|
||||
|
||||
var vertices = object.geometry.attributes.position.array;
|
||||
var numEdges = vertices.length / 3;
|
||||
var numTris = numEdges / 3;
|
||||
|
||||
var coords = new Float32Array( numEdges * 2 * 3 );
|
||||
|
||||
for ( var i = 0, l = numTris; i < l; i ++ ) {
|
||||
|
||||
for ( var j = 0; j < 3; j ++ ) {
|
||||
|
||||
var index = 18 * i + 6 * j;
|
||||
|
||||
var index1 = 9 * i + 3 * j;
|
||||
coords[ index + 0 ] = vertices[ index1 ];
|
||||
coords[ index + 1 ] = vertices[ index1 + 1 ];
|
||||
coords[ index + 2 ] = vertices[ index1 + 2 ];
|
||||
|
||||
var index2 = 9 * i + 3 * ( ( j + 1 ) % 3 );
|
||||
coords[ index + 3 ] = vertices[ index2 ];
|
||||
coords[ index + 4 ] = vertices[ index2 + 1 ];
|
||||
coords[ index + 5 ] = vertices[ index2 + 2 ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
THREE.Segment.call( this, geometry, new THREE.LineBasicMaterial( { color: color } ), THREE.LinePieces );
|
||||
|
||||
this.matrixAutoUpdate = false;
|
||||
this.matrixWorld = object.matrixWorld;
|
||||
|
||||
};
|
||||
|
||||
THREE.WireframeHelper.prototype = Object.create( THREE.Segment.prototype );
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.ImmediateRenderObject = function () {
|
||||
|
||||
THREE.Object3D.call( this );
|
||||
|
||||
this.render = function ( renderCallback ) {};
|
||||
|
||||
};
|
||||
|
||||
THREE.ImmediateRenderObject.prototype = Object.create( THREE.Object3D.prototype );
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
/**
|
||||
* @author mikael emtinger / http://gomo.se/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.LensFlare = function ( texture, size, distance, blending, color ) {
|
||||
|
||||
THREE.Object3D.call( this );
|
||||
|
||||
this.lensFlares = [];
|
||||
|
||||
this.positionScreen = new THREE.Vector3();
|
||||
this.customUpdateCallback = undefined;
|
||||
|
||||
if( texture !== undefined ) {
|
||||
|
||||
this.add( texture, size, distance, blending, color );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.LensFlare.prototype = Object.create( THREE.Object3D.prototype );
|
||||
|
||||
|
||||
/*
|
||||
* Add: adds another flare
|
||||
*/
|
||||
|
||||
THREE.LensFlare.prototype.add = function ( texture, size, distance, blending, color, opacity ) {
|
||||
|
||||
if( size === undefined ) size = - 1;
|
||||
if( distance === undefined ) distance = 0;
|
||||
if( opacity === undefined ) opacity = 1;
|
||||
if( color === undefined ) color = new THREE.Color( 0xffffff );
|
||||
if( blending === undefined ) blending = THREE.NormalBlending;
|
||||
|
||||
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: opacity, // opacity
|
||||
color: color, // color
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,307 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.MorphBlendMesh = function( geometry, material ) {
|
||||
|
||||
THREE.Mesh.call( this, geometry, material );
|
||||
|
||||
this.animationsMap = {};
|
||||
this.animationsList = [];
|
||||
|
||||
// prepare default animation
|
||||
// (all frames played together in 1 second)
|
||||
|
||||
var numFrames = this.geometry.morphTargets.length;
|
||||
|
||||
var name = "__default";
|
||||
|
||||
var startFrame = 0;
|
||||
var endFrame = numFrames - 1;
|
||||
|
||||
var fps = numFrames / 1;
|
||||
|
||||
this.createAnimation( name, startFrame, endFrame, fps );
|
||||
this.setAnimationWeight( name, 1 );
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype = Object.create( THREE.Mesh.prototype );
|
||||
|
||||
THREE.MorphBlendMesh.prototype.createAnimation = function ( name, start, end, fps ) {
|
||||
|
||||
var animation = {
|
||||
|
||||
startFrame: start,
|
||||
endFrame: end,
|
||||
|
||||
length: end - start + 1,
|
||||
|
||||
fps: fps,
|
||||
duration: ( end - start ) / fps,
|
||||
|
||||
lastFrame: 0,
|
||||
currentFrame: 0,
|
||||
|
||||
active: false,
|
||||
|
||||
time: 0,
|
||||
direction: 1,
|
||||
weight: 1,
|
||||
|
||||
directionBackwards: false,
|
||||
mirroredLoop: false
|
||||
|
||||
};
|
||||
|
||||
this.animationsMap[ name ] = animation;
|
||||
this.animationsList.push( animation );
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype.autoCreateAnimations = function ( fps ) {
|
||||
|
||||
var pattern = /([a-z]+)_?(\d+)/;
|
||||
|
||||
var firstAnimation, frameRanges = {};
|
||||
|
||||
var geometry = this.geometry;
|
||||
|
||||
for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) {
|
||||
|
||||
var morph = geometry.morphTargets[ i ];
|
||||
var chunks = morph.name.match( pattern );
|
||||
|
||||
if ( chunks && chunks.length > 1 ) {
|
||||
|
||||
var name = chunks[ 1 ];
|
||||
var num = chunks[ 2 ];
|
||||
|
||||
if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: - Infinity };
|
||||
|
||||
var range = frameRanges[ name ];
|
||||
|
||||
if ( i < range.start ) range.start = i;
|
||||
if ( i > range.end ) range.end = i;
|
||||
|
||||
if ( ! firstAnimation ) firstAnimation = name;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for ( var name in frameRanges ) {
|
||||
|
||||
var range = frameRanges[ name ];
|
||||
this.createAnimation( name, range.start, range.end, fps );
|
||||
|
||||
}
|
||||
|
||||
this.firstAnimation = firstAnimation;
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype.setAnimationDirectionForward = function ( name ) {
|
||||
|
||||
var animation = this.animationsMap[ name ];
|
||||
|
||||
if ( animation ) {
|
||||
|
||||
animation.direction = 1;
|
||||
animation.directionBackwards = false;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward = function ( name ) {
|
||||
|
||||
var animation = this.animationsMap[ name ];
|
||||
|
||||
if ( animation ) {
|
||||
|
||||
animation.direction = - 1;
|
||||
animation.directionBackwards = true;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype.setAnimationFPS = function ( name, fps ) {
|
||||
|
||||
var animation = this.animationsMap[ name ];
|
||||
|
||||
if ( animation ) {
|
||||
|
||||
animation.fps = fps;
|
||||
animation.duration = ( animation.end - animation.start ) / animation.fps;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype.setAnimationDuration = function ( name, duration ) {
|
||||
|
||||
var animation = this.animationsMap[ name ];
|
||||
|
||||
if ( animation ) {
|
||||
|
||||
animation.duration = duration;
|
||||
animation.fps = ( animation.end - animation.start ) / animation.duration;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype.setAnimationWeight = function ( name, weight ) {
|
||||
|
||||
var animation = this.animationsMap[ name ];
|
||||
|
||||
if ( animation ) {
|
||||
|
||||
animation.weight = weight;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype.setAnimationTime = function ( name, time ) {
|
||||
|
||||
var animation = this.animationsMap[ name ];
|
||||
|
||||
if ( animation ) {
|
||||
|
||||
animation.time = time;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype.getAnimationTime = function ( name ) {
|
||||
|
||||
var time = 0;
|
||||
|
||||
var animation = this.animationsMap[ name ];
|
||||
|
||||
if ( animation ) {
|
||||
|
||||
time = animation.time;
|
||||
|
||||
}
|
||||
|
||||
return time;
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype.getAnimationDuration = function ( name ) {
|
||||
|
||||
var duration = - 1;
|
||||
|
||||
var animation = this.animationsMap[ name ];
|
||||
|
||||
if ( animation ) {
|
||||
|
||||
duration = animation.duration;
|
||||
|
||||
}
|
||||
|
||||
return duration;
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype.playAnimation = function ( name ) {
|
||||
|
||||
var animation = this.animationsMap[ name ];
|
||||
|
||||
if ( animation ) {
|
||||
|
||||
animation.time = 0;
|
||||
animation.active = true;
|
||||
|
||||
} else {
|
||||
|
||||
console.warn( "animation[" + name + "] undefined" );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype.stopAnimation = function ( name ) {
|
||||
|
||||
var animation = this.animationsMap[ name ];
|
||||
|
||||
if ( animation ) {
|
||||
|
||||
animation.active = false;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.MorphBlendMesh.prototype.update = function ( delta ) {
|
||||
|
||||
for ( var i = 0, il = this.animationsList.length; i < il; i ++ ) {
|
||||
|
||||
var animation = this.animationsList[ i ];
|
||||
|
||||
if ( ! animation.active ) continue;
|
||||
|
||||
var frameTime = animation.duration / animation.length;
|
||||
|
||||
animation.time += animation.direction * delta;
|
||||
|
||||
if ( animation.mirroredLoop ) {
|
||||
|
||||
if ( animation.time > animation.duration || animation.time < 0 ) {
|
||||
|
||||
animation.direction *= - 1;
|
||||
|
||||
if ( animation.time > animation.duration ) {
|
||||
|
||||
animation.time = animation.duration;
|
||||
animation.directionBackwards = true;
|
||||
|
||||
}
|
||||
|
||||
if ( animation.time < 0 ) {
|
||||
|
||||
animation.time = 0;
|
||||
animation.directionBackwards = false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
animation.time = animation.time % animation.duration;
|
||||
|
||||
if ( animation.time < 0 ) animation.time += animation.duration;
|
||||
|
||||
}
|
||||
|
||||
var keyframe = animation.startFrame + THREE.Math.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 );
|
||||
var weight = animation.weight;
|
||||
|
||||
if ( keyframe !== animation.currentFrame ) {
|
||||
|
||||
this.morphTargetInfluences[ animation.lastFrame ] = 0;
|
||||
this.morphTargetInfluences[ animation.currentFrame ] = 1 * weight;
|
||||
|
||||
this.morphTargetInfluences[ keyframe ] = 0;
|
||||
|
||||
animation.lastFrame = animation.currentFrame;
|
||||
animation.currentFrame = keyframe;
|
||||
|
||||
}
|
||||
|
||||
var mix = ( animation.time % frameTime ) / frameTime;
|
||||
|
||||
if ( animation.directionBackwards ) mix = 1 - mix;
|
||||
|
||||
this.morphTargetInfluences[ animation.currentFrame ] = mix * weight;
|
||||
this.morphTargetInfluences[ animation.lastFrame ] = ( 1 - mix ) * weight;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,205 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.DepthPassPlugin = function () {
|
||||
|
||||
this.enabled = false;
|
||||
this.renderTarget = null;
|
||||
|
||||
var _gl,
|
||||
_renderer,
|
||||
_depthMaterial, _depthMaterialMorph, _depthMaterialSkin, _depthMaterialMorphSkin,
|
||||
|
||||
_frustum = new THREE.Frustum(),
|
||||
_projScreenMatrix = new THREE.Matrix4(),
|
||||
_renderList = [];
|
||||
|
||||
this.init = function ( renderer ) {
|
||||
|
||||
_gl = renderer.context;
|
||||
_renderer = renderer;
|
||||
|
||||
var depthShader = THREE.ShaderLib[ "depthRGBA" ];
|
||||
var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
|
||||
|
||||
_depthMaterial = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms } );
|
||||
_depthMaterialMorph = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true } );
|
||||
_depthMaterialSkin = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, skinning: true } );
|
||||
_depthMaterialMorphSkin = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true, skinning: true } );
|
||||
|
||||
_depthMaterial._shadowPass = true;
|
||||
_depthMaterialMorph._shadowPass = true;
|
||||
_depthMaterialSkin._shadowPass = true;
|
||||
_depthMaterialMorphSkin._shadowPass = true;
|
||||
|
||||
};
|
||||
|
||||
this.render = function ( scene, camera ) {
|
||||
|
||||
if ( ! this.enabled ) return;
|
||||
|
||||
this.update( scene, camera );
|
||||
|
||||
};
|
||||
|
||||
this.update = function ( scene, camera ) {
|
||||
|
||||
var i, il, j, jl, n,
|
||||
|
||||
program, buffer, material,
|
||||
webglObject, object, light,
|
||||
renderList,
|
||||
|
||||
fog = null;
|
||||
|
||||
// set GL state for depth map
|
||||
|
||||
_gl.clearColor( 1, 1, 1, 1 );
|
||||
_gl.disable( _gl.BLEND );
|
||||
|
||||
_renderer.setDepthTest( true );
|
||||
|
||||
// update scene
|
||||
|
||||
if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
|
||||
|
||||
// update camera matrices and frustum
|
||||
|
||||
camera.matrixWorldInverse.getInverse( camera.matrixWorld );
|
||||
|
||||
_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
|
||||
_frustum.setFromMatrix( _projScreenMatrix );
|
||||
|
||||
// render depth map
|
||||
|
||||
_renderer.setRenderTarget( this.renderTarget );
|
||||
_renderer.clear();
|
||||
|
||||
// set object matrices & frustum culling
|
||||
|
||||
_renderList.length = 0;
|
||||
projectObject(scene,scene,camera);
|
||||
|
||||
// render regular objects
|
||||
|
||||
var objectMaterial, useMorphing, useSkinning;
|
||||
|
||||
for ( j = 0, jl = _renderList.length; j < jl; j ++ ) {
|
||||
|
||||
webglObject = _renderList[ j ];
|
||||
|
||||
object = webglObject.object;
|
||||
buffer = webglObject.buffer;
|
||||
|
||||
// todo: create proper depth material for particles
|
||||
|
||||
if ( object instanceof THREE.PointCloud && ! object.customDepthMaterial ) continue;
|
||||
|
||||
objectMaterial = getObjectMaterial( object );
|
||||
|
||||
if ( objectMaterial ) _renderer.setMaterialFaces( object.material );
|
||||
|
||||
useMorphing = object.geometry.morphTargets !== undefined && object.geometry.morphTargets.length > 0 && objectMaterial.morphTargets;
|
||||
useSkinning = object instanceof THREE.SkinnedMesh && objectMaterial.skinning;
|
||||
|
||||
if ( object.customDepthMaterial ) {
|
||||
|
||||
material = object.customDepthMaterial;
|
||||
|
||||
} else if ( useSkinning ) {
|
||||
|
||||
material = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin;
|
||||
|
||||
} else if ( useMorphing ) {
|
||||
|
||||
material = _depthMaterialMorph;
|
||||
|
||||
} else {
|
||||
|
||||
material = _depthMaterial;
|
||||
|
||||
}
|
||||
|
||||
if ( buffer instanceof THREE.BufferGeometry ) {
|
||||
|
||||
_renderer.renderBufferDirect( camera, scene.__lights, fog, material, buffer, object );
|
||||
|
||||
} else {
|
||||
|
||||
_renderer.renderBuffer( camera, scene.__lights, fog, material, buffer, object );
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// set matrices and render immediate objects
|
||||
|
||||
renderList = scene.__webglObjectsImmediate;
|
||||
|
||||
for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
|
||||
|
||||
webglObject = renderList[ j ];
|
||||
object = webglObject.object;
|
||||
|
||||
if ( object.visible ) {
|
||||
|
||||
object._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
|
||||
|
||||
_renderer.renderImmediateObject( camera, scene.__lights, fog, _depthMaterial, object );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// restore GL state
|
||||
|
||||
var clearColor = _renderer.getClearColor(),
|
||||
clearAlpha = _renderer.getClearAlpha();
|
||||
|
||||
_gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha );
|
||||
_gl.enable( _gl.BLEND );
|
||||
|
||||
};
|
||||
|
||||
function projectObject(scene, object,camera){
|
||||
|
||||
if ( object.visible ) {
|
||||
|
||||
var webglObjects = scene.__webglObjects[object.id];
|
||||
|
||||
if (webglObjects && (object.frustumCulled === false || _frustum.intersectsObject( object ) === true) ) {
|
||||
|
||||
|
||||
for (var i = 0, l = webglObjects.length; i < l; i++){
|
||||
|
||||
var webglObject = webglObjects[i];
|
||||
|
||||
object._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
|
||||
_renderList.push(webglObject);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for(var i = 0, l = object.children.length; i < l; i++) {
|
||||
|
||||
projectObject(scene, object.children[i], camera);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// For the moment just ignore objects that have multiple materials with different animation methods
|
||||
// Only the first material will be taken into account for deciding which depth material to use
|
||||
|
||||
function getObjectMaterial( object ) {
|
||||
|
||||
return object.material instanceof THREE.MeshFaceMaterial
|
||||
? object.material.materials[ 0 ]
|
||||
: object.material;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -1,312 +0,0 @@
|
|||
/**
|
||||
* @author mikael emtinger / http://gomo.se/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.LensFlarePlugin = function () {
|
||||
|
||||
var flares = [];
|
||||
|
||||
var _gl, _renderer, _precision, _lensFlare = {};
|
||||
|
||||
this.init = function ( renderer ) {
|
||||
|
||||
_gl = renderer.context;
|
||||
_renderer = renderer;
|
||||
|
||||
_precision = renderer.getPrecision();
|
||||
|
||||
_lensFlare.vertices = new Float32Array( 8 + 8 );
|
||||
_lensFlare.faces = new Uint16Array( 6 );
|
||||
|
||||
var 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;
|
||||
|
||||
// buffers
|
||||
|
||||
_lensFlare.vertexBuffer = _gl.createBuffer();
|
||||
_lensFlare.elementBuffer = _gl.createBuffer();
|
||||
|
||||
_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 );
|
||||
|
||||
// textures
|
||||
|
||||
_lensFlare.tempTexture = _gl.createTexture();
|
||||
_lensFlare.occlusionTexture = _gl.createTexture();
|
||||
|
||||
_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 = createProgram( THREE.ShaderFlares[ "lensFlare" ], _precision );
|
||||
|
||||
} else {
|
||||
|
||||
_lensFlare.hasVertexTexture = true;
|
||||
_lensFlare.program = createProgram( THREE.ShaderFlares[ "lensFlareVertexTexture" ], _precision );
|
||||
|
||||
}
|
||||
|
||||
_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.color = _gl.getUniformLocation( _lensFlare.program, "color" );
|
||||
_lensFlare.uniforms.scale = _gl.getUniformLocation( _lensFlare.program, "scale" );
|
||||
_lensFlare.uniforms.rotation = _gl.getUniformLocation( _lensFlare.program, "rotation" );
|
||||
_lensFlare.uniforms.screenPosition = _gl.getUniformLocation( _lensFlare.program, "screenPosition" );
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Render lens flares
|
||||
* Method: renders 16x16 0xff00ff-colored points scattered over the light source area,
|
||||
* reads these back and calculates occlusion.
|
||||
* Then _lensFlare.update_lensFlares() is called to re-position and
|
||||
* update transparency of flares. Then they are rendered.
|
||||
*
|
||||
*/
|
||||
|
||||
this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
|
||||
|
||||
flares.length = 0;
|
||||
|
||||
scene.traverseVisible( function ( child ) {
|
||||
|
||||
if ( child instanceof THREE.LensFlare ) {
|
||||
|
||||
flares.push( child );
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
if ( flares.length === 0 ) return;
|
||||
|
||||
var tempPosition = new THREE.Vector3();
|
||||
|
||||
var invAspect = viewportHeight / viewportWidth,
|
||||
halfViewportWidth = viewportWidth * 0.5,
|
||||
halfViewportHeight = viewportHeight * 0.5;
|
||||
|
||||
var size = 16 / viewportHeight,
|
||||
scale = new THREE.Vector2( size * invAspect, size );
|
||||
|
||||
var screenPosition = new THREE.Vector3( 1, 1, 0 ),
|
||||
screenPositionPixels = new THREE.Vector2( 1, 1 );
|
||||
|
||||
var uniforms = _lensFlare.uniforms,
|
||||
attributes = _lensFlare.attributes;
|
||||
|
||||
// set _lensFlare program and reset blending
|
||||
|
||||
_gl.useProgram( _lensFlare.program );
|
||||
|
||||
_gl.enableVertexAttribArray( _lensFlare.attributes.vertex );
|
||||
_gl.enableVertexAttribArray( _lensFlare.attributes.uv );
|
||||
|
||||
// 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 );
|
||||
|
||||
for ( var i = 0, l = flares.length; i < l; i ++ ) {
|
||||
|
||||
size = 16 / viewportHeight;
|
||||
scale.set( size * invAspect, size );
|
||||
|
||||
// calc object screen position
|
||||
|
||||
var flare = flares[ i ];
|
||||
|
||||
tempPosition.set( flare.matrixWorld.elements[12], flare.matrixWorld.elements[13], flare.matrixWorld.elements[14] );
|
||||
|
||||
tempPosition.applyMatrix4( camera.matrixWorldInverse );
|
||||
tempPosition.applyProjection( camera.projectionMatrix );
|
||||
|
||||
// setup arrays for gl programs
|
||||
|
||||
screenPosition.copy( tempPosition )
|
||||
|
||||
screenPositionPixels.x = screenPosition.x * halfViewportWidth + halfViewportWidth;
|
||||
screenPositionPixels.y = screenPosition.y * halfViewportHeight + halfViewportHeight;
|
||||
|
||||
// screen cull
|
||||
|
||||
if ( _lensFlare.hasVertexTexture || (
|
||||
screenPositionPixels.x > 0 &&
|
||||
screenPositionPixels.x < viewportWidth &&
|
||||
screenPositionPixels.y > 0 &&
|
||||
screenPositionPixels.y < viewportHeight ) ) {
|
||||
|
||||
// save current RGB to temp texture
|
||||
|
||||
_gl.activeTexture( _gl.TEXTURE1 );
|
||||
_gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
|
||||
_gl.copyTexImage2D( _gl.TEXTURE_2D, 0, _gl.RGB, screenPositionPixels.x - 8, screenPositionPixels.y - 8, 16, 16, 0 );
|
||||
|
||||
|
||||
// render pink quad
|
||||
|
||||
_gl.uniform1i( uniforms.renderType, 0 );
|
||||
_gl.uniform2f( uniforms.scale, scale.x, scale.y );
|
||||
_gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
|
||||
|
||||
_gl.disable( _gl.BLEND );
|
||||
_gl.enable( _gl.DEPTH_TEST );
|
||||
|
||||
_gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
|
||||
|
||||
|
||||
// copy result to occlusionMap
|
||||
|
||||
_gl.activeTexture( _gl.TEXTURE0 );
|
||||
_gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.occlusionTexture );
|
||||
_gl.copyTexImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, screenPositionPixels.x - 8, screenPositionPixels.y - 8, 16, 16, 0 );
|
||||
|
||||
|
||||
// restore graphics
|
||||
|
||||
_gl.uniform1i( uniforms.renderType, 1 );
|
||||
_gl.disable( _gl.DEPTH_TEST );
|
||||
|
||||
_gl.activeTexture( _gl.TEXTURE1 );
|
||||
_gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
|
||||
_gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
|
||||
|
||||
|
||||
// update object positions
|
||||
|
||||
flare.positionScreen.copy( screenPosition )
|
||||
|
||||
if ( flare.customUpdateCallback ) {
|
||||
|
||||
flare.customUpdateCallback( flare );
|
||||
|
||||
} else {
|
||||
|
||||
flare.updateLensFlares();
|
||||
|
||||
}
|
||||
|
||||
// render flares
|
||||
|
||||
_gl.uniform1i( uniforms.renderType, 2 );
|
||||
_gl.enable( _gl.BLEND );
|
||||
|
||||
for ( var j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) {
|
||||
|
||||
var sprite = flare.lensFlares[ j ];
|
||||
|
||||
if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) {
|
||||
|
||||
screenPosition.x = sprite.x;
|
||||
screenPosition.y = sprite.y;
|
||||
screenPosition.z = sprite.z;
|
||||
|
||||
size = sprite.size * sprite.scale / viewportHeight;
|
||||
|
||||
scale.x = size * invAspect;
|
||||
scale.y = size;
|
||||
|
||||
_gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
|
||||
_gl.uniform2f( uniforms.scale, scale.x, scale.y );
|
||||
_gl.uniform1f( uniforms.rotation, sprite.rotation );
|
||||
|
||||
_gl.uniform1f( uniforms.opacity, sprite.opacity );
|
||||
_gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b );
|
||||
|
||||
_renderer.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst );
|
||||
_renderer.setTexture( sprite.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( true );
|
||||
|
||||
};
|
||||
|
||||
function createProgram ( shader, precision ) {
|
||||
|
||||
var program = _gl.createProgram();
|
||||
|
||||
var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
|
||||
var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
|
||||
|
||||
var prefix = "precision " + precision + " float;\n";
|
||||
|
||||
_gl.shaderSource( fragmentShader, prefix + shader.fragmentShader );
|
||||
_gl.shaderSource( vertexShader, prefix + shader.vertexShader );
|
||||
|
||||
_gl.compileShader( fragmentShader );
|
||||
_gl.compileShader( vertexShader );
|
||||
|
||||
_gl.attachShader( program, fragmentShader );
|
||||
_gl.attachShader( program, vertexShader );
|
||||
|
||||
_gl.linkProgram( program );
|
||||
|
||||
return program;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -1,503 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.ShadowMapPlugin = function () {
|
||||
|
||||
var _gl,
|
||||
_renderer,
|
||||
_depthMaterial, _depthMaterialMorph, _depthMaterialSkin, _depthMaterialMorphSkin,
|
||||
|
||||
_frustum = new THREE.Frustum(),
|
||||
_projScreenMatrix = new THREE.Matrix4(),
|
||||
|
||||
_min = new THREE.Vector3(),
|
||||
_max = new THREE.Vector3(),
|
||||
|
||||
_matrixPosition = new THREE.Vector3(),
|
||||
|
||||
_renderList = [];
|
||||
|
||||
this.init = function ( renderer ) {
|
||||
|
||||
_gl = renderer.context;
|
||||
_renderer = renderer;
|
||||
|
||||
var depthShader = THREE.ShaderLib[ "depthRGBA" ];
|
||||
var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
|
||||
|
||||
_depthMaterial = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms } );
|
||||
_depthMaterialMorph = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true } );
|
||||
_depthMaterialSkin = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, skinning: true } );
|
||||
_depthMaterialMorphSkin = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true, skinning: true } );
|
||||
|
||||
_depthMaterial._shadowPass = true;
|
||||
_depthMaterialMorph._shadowPass = true;
|
||||
_depthMaterialSkin._shadowPass = true;
|
||||
_depthMaterialMorphSkin._shadowPass = true;
|
||||
|
||||
};
|
||||
|
||||
this.render = function ( scene, camera ) {
|
||||
|
||||
if ( ! ( _renderer.shadowMapEnabled && _renderer.shadowMapAutoUpdate ) ) return;
|
||||
|
||||
this.update( scene, camera );
|
||||
|
||||
};
|
||||
|
||||
this.update = function ( scene, camera ) {
|
||||
|
||||
var i, il, j, jl, n,
|
||||
|
||||
shadowMap, shadowMatrix, shadowCamera,
|
||||
program, buffer, material,
|
||||
webglObject, object, light,
|
||||
|
||||
lights = [],
|
||||
k = 0,
|
||||
|
||||
fog = null;
|
||||
|
||||
// set GL state for depth map
|
||||
|
||||
_gl.clearColor( 1, 1, 1, 1 );
|
||||
_gl.disable( _gl.BLEND );
|
||||
|
||||
_gl.enable( _gl.CULL_FACE );
|
||||
_gl.frontFace( _gl.CCW );
|
||||
|
||||
if ( _renderer.shadowMapCullFace === THREE.CullFaceFront ) {
|
||||
|
||||
_gl.cullFace( _gl.FRONT );
|
||||
|
||||
} else {
|
||||
|
||||
_gl.cullFace( _gl.BACK );
|
||||
|
||||
}
|
||||
|
||||
_renderer.setDepthTest( true );
|
||||
|
||||
// preprocess lights
|
||||
// - skip lights that are not casting shadows
|
||||
// - create virtual lights for cascaded shadow maps
|
||||
|
||||
for ( i = 0, il = scene.__lights.length; i < il; i ++ ) {
|
||||
|
||||
light = scene.__lights[ i ];
|
||||
|
||||
if ( ! light.castShadow ) continue;
|
||||
|
||||
if ( ( light instanceof THREE.DirectionalLight ) && light.shadowCascade ) {
|
||||
|
||||
for ( n = 0; n < light.shadowCascadeCount; n ++ ) {
|
||||
|
||||
var virtualLight;
|
||||
|
||||
if ( ! light.shadowCascadeArray[ n ] ) {
|
||||
|
||||
virtualLight = createVirtualLight( light, n );
|
||||
virtualLight.originalCamera = camera;
|
||||
|
||||
var gyro = new THREE.Gyroscope();
|
||||
gyro.position.copy( light.shadowCascadeOffset );
|
||||
|
||||
gyro.add( virtualLight );
|
||||
gyro.add( virtualLight.target );
|
||||
|
||||
camera.add( gyro );
|
||||
|
||||
light.shadowCascadeArray[ n ] = virtualLight;
|
||||
|
||||
console.log( "Created virtualLight", virtualLight );
|
||||
|
||||
} else {
|
||||
|
||||
virtualLight = light.shadowCascadeArray[ n ];
|
||||
|
||||
}
|
||||
|
||||
updateVirtualLight( light, n );
|
||||
|
||||
lights[ k ] = virtualLight;
|
||||
k ++;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
lights[ k ] = light;
|
||||
k ++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// render depth map
|
||||
|
||||
for ( i = 0, il = lights.length; i < il; i ++ ) {
|
||||
|
||||
light = lights[ i ];
|
||||
|
||||
if ( ! light.shadowMap ) {
|
||||
|
||||
var shadowFilter = THREE.LinearFilter;
|
||||
|
||||
if ( _renderer.shadowMapType === THREE.PCFSoftShadowMap ) {
|
||||
|
||||
shadowFilter = THREE.NearestFilter;
|
||||
|
||||
}
|
||||
|
||||
var pars = { minFilter: shadowFilter, magFilter: shadowFilter, format: THREE.RGBAFormat };
|
||||
|
||||
light.shadowMap = new THREE.WebGLRenderTarget( light.shadowMapWidth, light.shadowMapHeight, pars );
|
||||
light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapHeight );
|
||||
|
||||
light.shadowMatrix = new THREE.Matrix4();
|
||||
|
||||
}
|
||||
|
||||
if ( ! light.shadowCamera ) {
|
||||
|
||||
if ( light instanceof THREE.SpotLight ) {
|
||||
|
||||
light.shadowCamera = new THREE.PerspectiveCamera( light.shadowCameraFov, light.shadowMapWidth / light.shadowMapHeight, light.shadowCameraNear, light.shadowCameraFar );
|
||||
|
||||
} else if ( light instanceof THREE.DirectionalLight ) {
|
||||
|
||||
light.shadowCamera = new THREE.OrthographicCamera( light.shadowCameraLeft, light.shadowCameraRight, light.shadowCameraTop, light.shadowCameraBottom, light.shadowCameraNear, light.shadowCameraFar );
|
||||
|
||||
} else {
|
||||
|
||||
console.error( "Unsupported light type for shadow" );
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
scene.add( light.shadowCamera );
|
||||
|
||||
if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
|
||||
|
||||
}
|
||||
|
||||
if ( light.shadowCameraVisible && ! light.cameraHelper ) {
|
||||
|
||||
light.cameraHelper = new THREE.CameraHelper( light.shadowCamera );
|
||||
light.shadowCamera.add( light.cameraHelper );
|
||||
|
||||
}
|
||||
|
||||
if ( light.isVirtual && virtualLight.originalCamera == camera ) {
|
||||
|
||||
updateShadowCamera( camera, light );
|
||||
|
||||
}
|
||||
|
||||
shadowMap = light.shadowMap;
|
||||
shadowMatrix = light.shadowMatrix;
|
||||
shadowCamera = light.shadowCamera;
|
||||
|
||||
shadowCamera.position.setFromMatrixPosition( light.matrixWorld );
|
||||
_matrixPosition.setFromMatrixPosition( light.target.matrixWorld );
|
||||
shadowCamera.lookAt( _matrixPosition );
|
||||
shadowCamera.updateMatrixWorld();
|
||||
|
||||
shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
|
||||
|
||||
if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
|
||||
if ( light.shadowCameraVisible ) light.cameraHelper.update();
|
||||
|
||||
// compute shadow matrix
|
||||
|
||||
shadowMatrix.set( 0.5, 0.0, 0.0, 0.5,
|
||||
0.0, 0.5, 0.0, 0.5,
|
||||
0.0, 0.0, 0.5, 0.5,
|
||||
0.0, 0.0, 0.0, 1.0 );
|
||||
|
||||
shadowMatrix.multiply( shadowCamera.projectionMatrix );
|
||||
shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
|
||||
|
||||
// update camera matrices and frustum
|
||||
|
||||
_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
|
||||
_frustum.setFromMatrix( _projScreenMatrix );
|
||||
|
||||
// render shadow map
|
||||
|
||||
_renderer.setRenderTarget( shadowMap );
|
||||
_renderer.clear();
|
||||
|
||||
// set object matrices & frustum culling
|
||||
|
||||
_renderList.length = 0;
|
||||
projectObject(scene,scene,shadowCamera);
|
||||
|
||||
|
||||
// render regular objects
|
||||
|
||||
var objectMaterial, useMorphing, useSkinning;
|
||||
|
||||
for ( j = 0, jl = _renderList.length; j < jl; j ++ ) {
|
||||
|
||||
webglObject = _renderList[ j ];
|
||||
|
||||
object = webglObject.object;
|
||||
buffer = webglObject.buffer;
|
||||
|
||||
// culling is overriden globally for all objects
|
||||
// while rendering depth map
|
||||
|
||||
// need to deal with MeshFaceMaterial somehow
|
||||
// in that case just use the first of material.materials for now
|
||||
// (proper solution would require to break objects by materials
|
||||
// similarly to regular rendering and then set corresponding
|
||||
// depth materials per each chunk instead of just once per object)
|
||||
|
||||
objectMaterial = getObjectMaterial( object );
|
||||
|
||||
useMorphing = object.geometry.morphTargets !== undefined && object.geometry.morphTargets.length > 0 && objectMaterial.morphTargets;
|
||||
useSkinning = object instanceof THREE.SkinnedMesh && objectMaterial.skinning;
|
||||
|
||||
if ( object.customDepthMaterial ) {
|
||||
|
||||
material = object.customDepthMaterial;
|
||||
|
||||
} else if ( useSkinning ) {
|
||||
|
||||
material = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin;
|
||||
|
||||
} else if ( useMorphing ) {
|
||||
|
||||
material = _depthMaterialMorph;
|
||||
|
||||
} else {
|
||||
|
||||
material = _depthMaterial;
|
||||
|
||||
}
|
||||
|
||||
_renderer.setMaterialFaces( objectMaterial );
|
||||
|
||||
if ( buffer instanceof THREE.BufferGeometry ) {
|
||||
|
||||
_renderer.renderBufferDirect( shadowCamera, scene.__lights, fog, material, buffer, object );
|
||||
|
||||
} else {
|
||||
|
||||
_renderer.renderBuffer( shadowCamera, scene.__lights, fog, material, buffer, object );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// set matrices and render immediate objects
|
||||
|
||||
var renderList = scene.__webglObjectsImmediate;
|
||||
|
||||
for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
|
||||
|
||||
webglObject = renderList[ j ];
|
||||
object = webglObject.object;
|
||||
|
||||
if ( object.visible && object.castShadow ) {
|
||||
|
||||
object._modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
|
||||
|
||||
_renderer.renderImmediateObject( shadowCamera, scene.__lights, fog, _depthMaterial, object );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// restore GL state
|
||||
|
||||
var clearColor = _renderer.getClearColor(),
|
||||
clearAlpha = _renderer.getClearAlpha();
|
||||
|
||||
_gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha );
|
||||
_gl.enable( _gl.BLEND );
|
||||
|
||||
if ( _renderer.shadowMapCullFace === THREE.CullFaceFront ) {
|
||||
|
||||
_gl.cullFace( _gl.BACK );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function projectObject(scene, object,shadowCamera){
|
||||
|
||||
if ( object.visible ) {
|
||||
|
||||
var webglObjects = scene.__webglObjects[object.id];
|
||||
|
||||
if (webglObjects && object.castShadow && (object.frustumCulled === false || _frustum.intersectsObject( object ) === true) ) {
|
||||
|
||||
|
||||
for (var i = 0, l = webglObjects.length; i < l; i++){
|
||||
|
||||
var webglObject = webglObjects[i];
|
||||
|
||||
object._modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
|
||||
_renderList.push(webglObject);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for(var i = 0, l = object.children.length; i < l; i++) {
|
||||
|
||||
projectObject(scene, object.children[i],shadowCamera);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function createVirtualLight( light, cascade ) {
|
||||
|
||||
var virtualLight = new THREE.DirectionalLight();
|
||||
|
||||
virtualLight.isVirtual = true;
|
||||
|
||||
virtualLight.onlyShadow = true;
|
||||
virtualLight.castShadow = true;
|
||||
|
||||
virtualLight.shadowCameraNear = light.shadowCameraNear;
|
||||
virtualLight.shadowCameraFar = light.shadowCameraFar;
|
||||
|
||||
virtualLight.shadowCameraLeft = light.shadowCameraLeft;
|
||||
virtualLight.shadowCameraRight = light.shadowCameraRight;
|
||||
virtualLight.shadowCameraBottom = light.shadowCameraBottom;
|
||||
virtualLight.shadowCameraTop = light.shadowCameraTop;
|
||||
|
||||
virtualLight.shadowCameraVisible = light.shadowCameraVisible;
|
||||
|
||||
virtualLight.shadowDarkness = light.shadowDarkness;
|
||||
|
||||
virtualLight.shadowBias = light.shadowCascadeBias[ cascade ];
|
||||
virtualLight.shadowMapWidth = light.shadowCascadeWidth[ cascade ];
|
||||
virtualLight.shadowMapHeight = light.shadowCascadeHeight[ cascade ];
|
||||
|
||||
virtualLight.pointsWorld = [];
|
||||
virtualLight.pointsFrustum = [];
|
||||
|
||||
var pointsWorld = virtualLight.pointsWorld,
|
||||
pointsFrustum = virtualLight.pointsFrustum;
|
||||
|
||||
for ( var i = 0; i < 8; i ++ ) {
|
||||
|
||||
pointsWorld[ i ] = new THREE.Vector3();
|
||||
pointsFrustum[ i ] = new THREE.Vector3();
|
||||
|
||||
}
|
||||
|
||||
var nearZ = light.shadowCascadeNearZ[ cascade ];
|
||||
var farZ = light.shadowCascadeFarZ[ cascade ];
|
||||
|
||||
pointsFrustum[ 0 ].set( - 1, - 1, nearZ );
|
||||
pointsFrustum[ 1 ].set( 1, - 1, nearZ );
|
||||
pointsFrustum[ 2 ].set( - 1, 1, nearZ );
|
||||
pointsFrustum[ 3 ].set( 1, 1, nearZ );
|
||||
|
||||
pointsFrustum[ 4 ].set( - 1, - 1, farZ );
|
||||
pointsFrustum[ 5 ].set( 1, - 1, farZ );
|
||||
pointsFrustum[ 6 ].set( - 1, 1, farZ );
|
||||
pointsFrustum[ 7 ].set( 1, 1, farZ );
|
||||
|
||||
return virtualLight;
|
||||
|
||||
}
|
||||
|
||||
// Synchronize virtual light with the original light
|
||||
|
||||
function updateVirtualLight( light, cascade ) {
|
||||
|
||||
var virtualLight = light.shadowCascadeArray[ cascade ];
|
||||
|
||||
virtualLight.position.copy( light.position );
|
||||
virtualLight.target.position.copy( light.target.position );
|
||||
virtualLight.lookAt( virtualLight.target );
|
||||
|
||||
virtualLight.shadowCameraVisible = light.shadowCameraVisible;
|
||||
virtualLight.shadowDarkness = light.shadowDarkness;
|
||||
|
||||
virtualLight.shadowBias = light.shadowCascadeBias[ cascade ];
|
||||
|
||||
var nearZ = light.shadowCascadeNearZ[ cascade ];
|
||||
var farZ = light.shadowCascadeFarZ[ cascade ];
|
||||
|
||||
var pointsFrustum = virtualLight.pointsFrustum;
|
||||
|
||||
pointsFrustum[ 0 ].z = nearZ;
|
||||
pointsFrustum[ 1 ].z = nearZ;
|
||||
pointsFrustum[ 2 ].z = nearZ;
|
||||
pointsFrustum[ 3 ].z = nearZ;
|
||||
|
||||
pointsFrustum[ 4 ].z = farZ;
|
||||
pointsFrustum[ 5 ].z = farZ;
|
||||
pointsFrustum[ 6 ].z = farZ;
|
||||
pointsFrustum[ 7 ].z = farZ;
|
||||
|
||||
}
|
||||
|
||||
// Fit shadow camera's ortho frustum to camera frustum
|
||||
|
||||
function updateShadowCamera( camera, light ) {
|
||||
|
||||
var shadowCamera = light.shadowCamera,
|
||||
pointsFrustum = light.pointsFrustum,
|
||||
pointsWorld = light.pointsWorld;
|
||||
|
||||
_min.set( Infinity, Infinity, Infinity );
|
||||
_max.set( - Infinity, - Infinity, - Infinity );
|
||||
|
||||
for ( var i = 0; i < 8; i ++ ) {
|
||||
|
||||
var p = pointsWorld[ i ];
|
||||
|
||||
p.copy( pointsFrustum[ i ] );
|
||||
THREE.ShadowMapPlugin.__projector.unprojectVector( p, camera );
|
||||
|
||||
p.applyMatrix4( shadowCamera.matrixWorldInverse );
|
||||
|
||||
if ( p.x < _min.x ) _min.x = p.x;
|
||||
if ( p.x > _max.x ) _max.x = p.x;
|
||||
|
||||
if ( p.y < _min.y ) _min.y = p.y;
|
||||
if ( p.y > _max.y ) _max.y = p.y;
|
||||
|
||||
if ( p.z < _min.z ) _min.z = p.z;
|
||||
if ( p.z > _max.z ) _max.z = p.z;
|
||||
|
||||
}
|
||||
|
||||
shadowCamera.left = _min.x;
|
||||
shadowCamera.right = _max.x;
|
||||
shadowCamera.top = _max.y;
|
||||
shadowCamera.bottom = _min.y;
|
||||
|
||||
// can't really fit near/far
|
||||
//shadowCamera.near = _min.z;
|
||||
//shadowCamera.far = _max.z;
|
||||
|
||||
shadowCamera.updateProjectionMatrix();
|
||||
|
||||
}
|
||||
|
||||
// For the moment just ignore objects that have multiple materials with different animation methods
|
||||
// Only the first material will be taken into account for deciding which depth material to use for shadow maps
|
||||
|
||||
function getObjectMaterial( object ) {
|
||||
|
||||
return object.material instanceof THREE.MeshFaceMaterial
|
||||
? object.material.materials[ 0 ]
|
||||
: object.material;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
THREE.ShadowMapPlugin.__projector = new THREE.Projector();
|
||||
|
|
@ -1,364 +0,0 @@
|
|||
/**
|
||||
* @author mikael emtinger / http://gomo.se/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.SpritePlugin = function () {
|
||||
|
||||
var _gl, _renderer, _texture;
|
||||
|
||||
var sprites = [];
|
||||
|
||||
var vertices, faces, vertexBuffer, elementBuffer;
|
||||
var program, attributes, uniforms;
|
||||
|
||||
this.init = function ( renderer ) {
|
||||
|
||||
_gl = renderer.context;
|
||||
_renderer = renderer;
|
||||
|
||||
vertices = new Float32Array( [
|
||||
- 0.5, - 0.5, 0, 0,
|
||||
0.5, - 0.5, 1, 0,
|
||||
0.5, 0.5, 1, 1,
|
||||
- 0.5, 0.5, 0, 1
|
||||
] );
|
||||
|
||||
faces = new Uint16Array( [
|
||||
0, 1, 2,
|
||||
0, 2, 3
|
||||
] );
|
||||
|
||||
vertexBuffer = _gl.createBuffer();
|
||||
elementBuffer = _gl.createBuffer();
|
||||
|
||||
_gl.bindBuffer( _gl.ARRAY_BUFFER, vertexBuffer );
|
||||
_gl.bufferData( _gl.ARRAY_BUFFER, vertices, _gl.STATIC_DRAW );
|
||||
|
||||
_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
|
||||
_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, faces, _gl.STATIC_DRAW );
|
||||
|
||||
program = createProgram();
|
||||
|
||||
attributes = {
|
||||
position: _gl.getAttribLocation ( program, 'position' ),
|
||||
uv: _gl.getAttribLocation ( program, 'uv' )
|
||||
};
|
||||
|
||||
uniforms = {
|
||||
uvOffset: _gl.getUniformLocation( program, 'uvOffset' ),
|
||||
uvScale: _gl.getUniformLocation( program, 'uvScale' ),
|
||||
|
||||
rotation: _gl.getUniformLocation( program, 'rotation' ),
|
||||
scale: _gl.getUniformLocation( program, 'scale' ),
|
||||
|
||||
color: _gl.getUniformLocation( program, 'color' ),
|
||||
map: _gl.getUniformLocation( program, 'map' ),
|
||||
opacity: _gl.getUniformLocation( program, 'opacity' ),
|
||||
|
||||
modelViewMatrix: _gl.getUniformLocation( program, 'modelViewMatrix' ),
|
||||
projectionMatrix: _gl.getUniformLocation( program, 'projectionMatrix' ),
|
||||
|
||||
fogType: _gl.getUniformLocation( program, 'fogType' ),
|
||||
fogDensity: _gl.getUniformLocation( program, 'fogDensity' ),
|
||||
fogNear: _gl.getUniformLocation( program, 'fogNear' ),
|
||||
fogFar: _gl.getUniformLocation( program, 'fogFar' ),
|
||||
fogColor: _gl.getUniformLocation( program, 'fogColor' ),
|
||||
|
||||
alphaTest: _gl.getUniformLocation( program, 'alphaTest' )
|
||||
};
|
||||
|
||||
var canvas = document.createElement( 'canvas' );
|
||||
canvas.width = 8;
|
||||
canvas.height = 8;
|
||||
|
||||
var context = canvas.getContext( '2d' );
|
||||
context.fillStyle = 'white';
|
||||
context.fillRect( 0, 0, 8, 8 );
|
||||
|
||||
_texture = new THREE.Texture( canvas );
|
||||
_texture.needsUpdate = true;
|
||||
|
||||
};
|
||||
|
||||
this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
|
||||
|
||||
sprites.length = 0;
|
||||
|
||||
scene.traverseVisible( function ( child ) {
|
||||
|
||||
if ( child instanceof THREE.Sprite ) {
|
||||
|
||||
sprites.push( child );
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
if ( sprites.length === 0 ) return;
|
||||
|
||||
// setup gl
|
||||
|
||||
_gl.useProgram( program );
|
||||
|
||||
_gl.enableVertexAttribArray( attributes.position );
|
||||
_gl.enableVertexAttribArray( attributes.uv );
|
||||
|
||||
_gl.disable( _gl.CULL_FACE );
|
||||
_gl.enable( _gl.BLEND );
|
||||
|
||||
_gl.bindBuffer( _gl.ARRAY_BUFFER, 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, elementBuffer );
|
||||
|
||||
_gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
|
||||
|
||||
_gl.activeTexture( _gl.TEXTURE0 );
|
||||
_gl.uniform1i( uniforms.map, 0 );
|
||||
|
||||
var oldFogType = 0;
|
||||
var sceneFogType = 0;
|
||||
var fog = scene.fog;
|
||||
|
||||
if ( fog ) {
|
||||
|
||||
_gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b );
|
||||
|
||||
if ( fog instanceof THREE.Fog ) {
|
||||
|
||||
_gl.uniform1f( uniforms.fogNear, fog.near );
|
||||
_gl.uniform1f( uniforms.fogFar, fog.far );
|
||||
|
||||
_gl.uniform1i( uniforms.fogType, 1 );
|
||||
oldFogType = 1;
|
||||
sceneFogType = 1;
|
||||
|
||||
} else if ( fog instanceof THREE.FogExp2 ) {
|
||||
|
||||
_gl.uniform1f( uniforms.fogDensity, fog.density );
|
||||
|
||||
_gl.uniform1i( uniforms.fogType, 2 );
|
||||
oldFogType = 2;
|
||||
sceneFogType = 2;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
_gl.uniform1i( uniforms.fogType, 0 );
|
||||
oldFogType = 0;
|
||||
sceneFogType = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// update positions and sort
|
||||
|
||||
for ( var i = 0, l = sprites.length; i < l; i ++ ) {
|
||||
|
||||
var sprite = sprites[ i ];
|
||||
var material = sprite.material;
|
||||
|
||||
sprite._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
|
||||
sprite.z = - sprite._modelViewMatrix.elements[ 14 ];
|
||||
|
||||
}
|
||||
|
||||
sprites.sort( painterSortStable );
|
||||
|
||||
// render all sprites
|
||||
|
||||
var scale = [];
|
||||
|
||||
for ( var i = 0, l = sprites.length; i < l; i ++ ) {
|
||||
|
||||
var sprite = sprites[ i ];
|
||||
var material = sprite.material;
|
||||
|
||||
_gl.uniform1f( uniforms.alphaTest, material.alphaTest );
|
||||
_gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite._modelViewMatrix.elements );
|
||||
|
||||
scale[ 0 ] = sprite.scale.x;
|
||||
scale[ 1 ] = sprite.scale.y;
|
||||
|
||||
var fogType = 0;
|
||||
|
||||
if ( scene.fog && material.fog ) {
|
||||
|
||||
fogType = sceneFogType;
|
||||
|
||||
}
|
||||
|
||||
if ( oldFogType !== fogType ) {
|
||||
|
||||
_gl.uniform1i( uniforms.fogType, fogType );
|
||||
oldFogType = fogType;
|
||||
|
||||
}
|
||||
|
||||
if ( material.map !== null ) {
|
||||
|
||||
_gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y );
|
||||
_gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y );
|
||||
|
||||
} else {
|
||||
|
||||
_gl.uniform2f( uniforms.uvOffset, 0, 0 );
|
||||
_gl.uniform2f( uniforms.uvScale, 1, 1 );
|
||||
|
||||
}
|
||||
|
||||
_gl.uniform1f( uniforms.opacity, material.opacity );
|
||||
_gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
|
||||
|
||||
_gl.uniform1f( uniforms.rotation, material.rotation );
|
||||
_gl.uniform2fv( uniforms.scale, scale );
|
||||
|
||||
_renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
|
||||
_renderer.setDepthTest( material.depthTest );
|
||||
_renderer.setDepthWrite( material.depthWrite );
|
||||
|
||||
if ( material.map && material.map.image && material.map.image.width ) {
|
||||
|
||||
_renderer.setTexture( material.map, 0 );
|
||||
|
||||
} else {
|
||||
|
||||
_renderer.setTexture( _texture, 0 );
|
||||
|
||||
}
|
||||
|
||||
_gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
|
||||
|
||||
}
|
||||
|
||||
// restore gl
|
||||
|
||||
_gl.enable( _gl.CULL_FACE );
|
||||
|
||||
};
|
||||
|
||||
function createProgram () {
|
||||
|
||||
var program = _gl.createProgram();
|
||||
|
||||
var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
|
||||
var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
|
||||
|
||||
_gl.shaderSource( vertexShader, [
|
||||
|
||||
'precision ' + _renderer.getPrecision() + ' float;',
|
||||
|
||||
'uniform mat4 modelViewMatrix;',
|
||||
'uniform mat4 projectionMatrix;',
|
||||
'uniform float rotation;',
|
||||
'uniform vec2 scale;',
|
||||
'uniform vec2 uvOffset;',
|
||||
'uniform vec2 uvScale;',
|
||||
|
||||
'attribute vec2 position;',
|
||||
'attribute vec2 uv;',
|
||||
|
||||
'varying vec2 vUV;',
|
||||
|
||||
'void main() {',
|
||||
|
||||
'vUV = uvOffset + uv * uvScale;',
|
||||
|
||||
'vec2 alignedPosition = position * scale;',
|
||||
|
||||
'vec2 rotatedPosition;',
|
||||
'rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;',
|
||||
'rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;',
|
||||
|
||||
'vec4 finalPosition;',
|
||||
|
||||
'finalPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );',
|
||||
'finalPosition.xy += rotatedPosition;',
|
||||
'finalPosition = projectionMatrix * finalPosition;',
|
||||
|
||||
'gl_Position = finalPosition;',
|
||||
|
||||
'}'
|
||||
|
||||
].join( '\n' ) );
|
||||
|
||||
_gl.shaderSource( fragmentShader, [
|
||||
|
||||
'precision ' + _renderer.getPrecision() + ' float;',
|
||||
|
||||
'uniform vec3 color;',
|
||||
'uniform sampler2D map;',
|
||||
'uniform float opacity;',
|
||||
|
||||
'uniform int fogType;',
|
||||
'uniform vec3 fogColor;',
|
||||
'uniform float fogDensity;',
|
||||
'uniform float fogNear;',
|
||||
'uniform float fogFar;',
|
||||
'uniform float alphaTest;',
|
||||
|
||||
'varying vec2 vUV;',
|
||||
|
||||
'void main() {',
|
||||
|
||||
'vec4 texture = texture2D( map, vUV );',
|
||||
|
||||
'if ( texture.a < alphaTest ) discard;',
|
||||
|
||||
'gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );',
|
||||
|
||||
'if ( fogType > 0 ) {',
|
||||
|
||||
'float depth = gl_FragCoord.z / gl_FragCoord.w;',
|
||||
'float fogFactor = 0.0;',
|
||||
|
||||
'if ( fogType == 1 ) {',
|
||||
|
||||
'fogFactor = smoothstep( fogNear, fogFar, depth );',
|
||||
|
||||
'} else {',
|
||||
|
||||
'const float LOG2 = 1.442695;',
|
||||
'float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );',
|
||||
'fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );',
|
||||
|
||||
'}',
|
||||
|
||||
'gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );',
|
||||
|
||||
'}',
|
||||
|
||||
'}'
|
||||
|
||||
].join( '\n' ) );
|
||||
|
||||
_gl.compileShader( vertexShader );
|
||||
_gl.compileShader( fragmentShader );
|
||||
|
||||
_gl.attachShader( program, vertexShader );
|
||||
_gl.attachShader( program, fragmentShader );
|
||||
|
||||
_gl.linkProgram( program );
|
||||
|
||||
return program;
|
||||
|
||||
};
|
||||
|
||||
function painterSortStable ( a, b ) {
|
||||
|
||||
if ( a.z !== b.z ) {
|
||||
|
||||
return b.z - a.z;
|
||||
|
||||
} else {
|
||||
|
||||
return b.id - a.id;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
/**
|
||||
* @author mikael emtinger / http://gomo.se/
|
||||
*/
|
||||
|
||||
THREE.ShaderFlares = {
|
||||
|
||||
'lensFlareVertexTexture': {
|
||||
|
||||
vertexShader: [
|
||||
|
||||
"uniform lowp int renderType;",
|
||||
|
||||
"uniform vec3 screenPosition;",
|
||||
"uniform vec2 scale;",
|
||||
"uniform float rotation;",
|
||||
|
||||
"uniform sampler2D occlusionMap;",
|
||||
|
||||
"attribute vec2 position;",
|
||||
"attribute vec2 uv;",
|
||||
|
||||
"varying vec2 vUV;",
|
||||
"varying float vVisibility;",
|
||||
|
||||
"void main() {",
|
||||
|
||||
"vUV = uv;",
|
||||
|
||||
"vec2 pos = position;",
|
||||
|
||||
"if( renderType == 2 ) {",
|
||||
|
||||
"vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );",
|
||||
"visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );",
|
||||
"visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );",
|
||||
"visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );",
|
||||
"visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );",
|
||||
"visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );",
|
||||
"visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );",
|
||||
"visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );",
|
||||
"visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );",
|
||||
|
||||
"vVisibility = visibility.r / 9.0;",
|
||||
"vVisibility *= 1.0 - visibility.g / 9.0;",
|
||||
"vVisibility *= visibility.b / 9.0;",
|
||||
"vVisibility *= 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: [
|
||||
|
||||
"uniform lowp int renderType;",
|
||||
|
||||
"uniform sampler2D map;",
|
||||
"uniform float opacity;",
|
||||
"uniform vec3 color;",
|
||||
|
||||
"varying vec2 vUV;",
|
||||
"varying float vVisibility;",
|
||||
|
||||
"void main() {",
|
||||
|
||||
// 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 texture = texture2D( map, vUV );",
|
||||
"texture.a *= opacity * vVisibility;",
|
||||
"gl_FragColor = texture;",
|
||||
"gl_FragColor.rgb *= color;",
|
||||
|
||||
"}",
|
||||
|
||||
"}"
|
||||
].join( "\n" )
|
||||
|
||||
},
|
||||
|
||||
|
||||
'lensFlare': {
|
||||
|
||||
vertexShader: [
|
||||
|
||||
"uniform lowp int renderType;",
|
||||
|
||||
"uniform vec3 screenPosition;",
|
||||
"uniform vec2 scale;",
|
||||
"uniform float rotation;",
|
||||
|
||||
"attribute vec2 position;",
|
||||
"attribute vec2 uv;",
|
||||
|
||||
"varying vec2 vUV;",
|
||||
|
||||
"void main() {",
|
||||
|
||||
"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: [
|
||||
|
||||
"precision mediump float;",
|
||||
|
||||
"uniform lowp int renderType;",
|
||||
|
||||
"uniform sampler2D map;",
|
||||
"uniform sampler2D occlusionMap;",
|
||||
"uniform float opacity;",
|
||||
"uniform vec3 color;",
|
||||
|
||||
"varying vec2 vUV;",
|
||||
|
||||
"void main() {",
|
||||
|
||||
// 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;",
|
||||
"visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) ).a;",
|
||||
"visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) ).a;",
|
||||
"visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) ).a;",
|
||||
"visibility = ( 1.0 - visibility / 4.0 );",
|
||||
|
||||
"vec4 texture = texture2D( map, vUV );",
|
||||
"texture.a *= opacity * visibility;",
|
||||
"gl_FragColor = texture;",
|
||||
"gl_FragColor.rgb *= color;",
|
||||
|
||||
"}",
|
||||
|
||||
"}"
|
||||
|
||||
].join( "\n" )
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.AmbientLight = function ( color ) {
|
||||
|
||||
THREE.Light.call( this, color );
|
||||
|
||||
};
|
||||
|
||||
THREE.AmbientLight.prototype = Object.create( THREE.Light.prototype );
|
||||
|
||||
THREE.AmbientLight.prototype.clone = function () {
|
||||
|
||||
var light = new THREE.AmbientLight();
|
||||
|
||||
THREE.Light.prototype.clone.call( this, light );
|
||||
|
||||
return light;
|
||||
|
||||
};
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
/**
|
||||
* @author MPanknin / http://www.redplant.de/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.AreaLight = function ( color, intensity ) {
|
||||
|
||||
THREE.Light.call( this, color );
|
||||
|
||||
this.normal = new THREE.Vector3( 0, - 1, 0 );
|
||||
this.right = new THREE.Vector3( 1, 0, 0 );
|
||||
|
||||
this.intensity = ( intensity !== undefined ) ? intensity : 1;
|
||||
|
||||
this.width = 1.0;
|
||||
this.height = 1.0;
|
||||
|
||||
this.constantAttenuation = 1.5;
|
||||
this.linearAttenuation = 0.5;
|
||||
this.quadraticAttenuation = 0.1;
|
||||
|
||||
};
|
||||
|
||||
THREE.AreaLight.prototype = Object.create( THREE.Light.prototype );
|
||||
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.DirectionalLight = function ( color, intensity ) {
|
||||
|
||||
THREE.Light.call( this, color );
|
||||
|
||||
this.position.set( 0, 1, 0 );
|
||||
this.target = new THREE.Object3D();
|
||||
|
||||
this.intensity = ( intensity !== undefined ) ? intensity : 1;
|
||||
|
||||
this.castShadow = false;
|
||||
this.onlyShadow = false;
|
||||
|
||||
//
|
||||
|
||||
this.shadowCameraNear = 50;
|
||||
this.shadowCameraFar = 5000;
|
||||
|
||||
this.shadowCameraLeft = - 500;
|
||||
this.shadowCameraRight = 500;
|
||||
this.shadowCameraTop = 500;
|
||||
this.shadowCameraBottom = - 500;
|
||||
|
||||
this.shadowCameraVisible = false;
|
||||
|
||||
this.shadowBias = 0;
|
||||
this.shadowDarkness = 0.5;
|
||||
|
||||
this.shadowMapWidth = 512;
|
||||
this.shadowMapHeight = 512;
|
||||
|
||||
//
|
||||
|
||||
this.shadowCascade = false;
|
||||
|
||||
this.shadowCascadeOffset = new THREE.Vector3( 0, 0, - 1000 );
|
||||
this.shadowCascadeCount = 2;
|
||||
|
||||
this.shadowCascadeBias = [ 0, 0, 0 ];
|
||||
this.shadowCascadeWidth = [ 512, 512, 512 ];
|
||||
this.shadowCascadeHeight = [ 512, 512, 512 ];
|
||||
|
||||
this.shadowCascadeNearZ = [ - 1.000, 0.990, 0.998 ];
|
||||
this.shadowCascadeFarZ = [ 0.990, 0.998, 1.000 ];
|
||||
|
||||
this.shadowCascadeArray = [];
|
||||
|
||||
//
|
||||
|
||||
this.shadowMap = null;
|
||||
this.shadowMapSize = null;
|
||||
this.shadowCamera = null;
|
||||
this.shadowMatrix = null;
|
||||
|
||||
};
|
||||
|
||||
THREE.DirectionalLight.prototype = Object.create( THREE.Light.prototype );
|
||||
|
||||
THREE.DirectionalLight.prototype.clone = function () {
|
||||
|
||||
var light = new THREE.DirectionalLight();
|
||||
|
||||
THREE.Light.prototype.clone.call( this, light );
|
||||
|
||||
light.target = this.target.clone();
|
||||
|
||||
light.intensity = this.intensity;
|
||||
|
||||
light.castShadow = this.castShadow;
|
||||
light.onlyShadow = this.onlyShadow;
|
||||
|
||||
//
|
||||
|
||||
light.shadowCameraNear = this.shadowCameraNear;
|
||||
light.shadowCameraFar = this.shadowCameraFar;
|
||||
|
||||
light.shadowCameraLeft = this.shadowCameraLeft;
|
||||
light.shadowCameraRight = this.shadowCameraRight;
|
||||
light.shadowCameraTop = this.shadowCameraTop;
|
||||
light.shadowCameraBottom = this.shadowCameraBottom;
|
||||
|
||||
light.shadowCameraVisible = this.shadowCameraVisible;
|
||||
|
||||
light.shadowBias = this.shadowBias;
|
||||
light.shadowDarkness = this.shadowDarkness;
|
||||
|
||||
light.shadowMapWidth = this.shadowMapWidth;
|
||||
light.shadowMapHeight = this.shadowMapHeight;
|
||||
|
||||
//
|
||||
|
||||
light.shadowCascade = this.shadowCascade;
|
||||
|
||||
light.shadowCascadeOffset.copy( this.shadowCascadeOffset );
|
||||
light.shadowCascadeCount = this.shadowCascadeCount;
|
||||
|
||||
light.shadowCascadeBias = this.shadowCascadeBias.slice( 0 );
|
||||
light.shadowCascadeWidth = this.shadowCascadeWidth.slice( 0 );
|
||||
light.shadowCascadeHeight = this.shadowCascadeHeight.slice( 0 );
|
||||
|
||||
light.shadowCascadeNearZ = this.shadowCascadeNearZ.slice( 0 );
|
||||
light.shadowCascadeFarZ = this.shadowCascadeFarZ.slice( 0 );
|
||||
|
||||
return light;
|
||||
|
||||
};
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.HemisphereLight = function ( skyColor, groundColor, intensity ) {
|
||||
|
||||
THREE.Light.call( this, skyColor );
|
||||
|
||||
this.position.set( 0, 100, 0 );
|
||||
|
||||
this.groundColor = new THREE.Color( groundColor );
|
||||
this.intensity = ( intensity !== undefined ) ? intensity : 1;
|
||||
|
||||
};
|
||||
|
||||
THREE.HemisphereLight.prototype = Object.create( THREE.Light.prototype );
|
||||
|
||||
THREE.HemisphereLight.prototype.clone = function () {
|
||||
|
||||
var light = new THREE.HemisphereLight();
|
||||
|
||||
THREE.Light.prototype.clone.call( this, light );
|
||||
|
||||
light.groundColor.copy( this.groundColor );
|
||||
light.intensity = this.intensity;
|
||||
|
||||
return light;
|
||||
|
||||
};
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.Light = function ( color ) {
|
||||
|
||||
THREE.Object3D.call( this );
|
||||
|
||||
this.color = new THREE.Color( color );
|
||||
|
||||
};
|
||||
|
||||
THREE.Light.prototype = Object.create( THREE.Object3D.prototype );
|
||||
|
||||
THREE.Light.prototype.clone = function ( light ) {
|
||||
|
||||
if ( light === undefined ) light = new THREE.Light();
|
||||
|
||||
THREE.Object3D.prototype.clone.call( this, light );
|
||||
|
||||
light.color.copy( this.color );
|
||||
|
||||
return light;
|
||||
|
||||
};
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.PointLight = function ( color, intensity, distance ) {
|
||||
|
||||
THREE.Light.call( this, color );
|
||||
|
||||
this.intensity = ( intensity !== undefined ) ? intensity : 1;
|
||||
this.distance = ( distance !== undefined ) ? distance : 0;
|
||||
|
||||
};
|
||||
|
||||
THREE.PointLight.prototype = Object.create( THREE.Light.prototype );
|
||||
|
||||
THREE.PointLight.prototype.clone = function () {
|
||||
|
||||
var light = new THREE.PointLight();
|
||||
|
||||
THREE.Light.prototype.clone.call( this, light );
|
||||
|
||||
light.intensity = this.intensity;
|
||||
light.distance = this.distance;
|
||||
|
||||
return light;
|
||||
|
||||
};
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.SpotLight = function ( color, intensity, distance, angle, exponent ) {
|
||||
|
||||
THREE.Light.call( this, color );
|
||||
|
||||
this.position.set( 0, 1, 0 );
|
||||
this.target = new THREE.Object3D();
|
||||
|
||||
this.intensity = ( intensity !== undefined ) ? intensity : 1;
|
||||
this.distance = ( distance !== undefined ) ? distance : 0;
|
||||
this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
|
||||
this.exponent = ( exponent !== undefined ) ? exponent : 10;
|
||||
|
||||
this.castShadow = false;
|
||||
this.onlyShadow = false;
|
||||
|
||||
//
|
||||
|
||||
this.shadowCameraNear = 50;
|
||||
this.shadowCameraFar = 5000;
|
||||
this.shadowCameraFov = 50;
|
||||
|
||||
this.shadowCameraVisible = false;
|
||||
|
||||
this.shadowBias = 0;
|
||||
this.shadowDarkness = 0.5;
|
||||
|
||||
this.shadowMapWidth = 512;
|
||||
this.shadowMapHeight = 512;
|
||||
|
||||
//
|
||||
|
||||
this.shadowMap = null;
|
||||
this.shadowMapSize = null;
|
||||
this.shadowCamera = null;
|
||||
this.shadowMatrix = null;
|
||||
|
||||
};
|
||||
|
||||
THREE.SpotLight.prototype = Object.create( THREE.Light.prototype );
|
||||
|
||||
THREE.SpotLight.prototype.clone = function () {
|
||||
|
||||
var light = new THREE.SpotLight();
|
||||
|
||||
THREE.Light.prototype.clone.call( this, light );
|
||||
|
||||
light.target = this.target.clone();
|
||||
|
||||
light.intensity = this.intensity;
|
||||
light.distance = this.distance;
|
||||
light.angle = this.angle;
|
||||
light.exponent = this.exponent;
|
||||
|
||||
light.castShadow = this.castShadow;
|
||||
light.onlyShadow = this.onlyShadow;
|
||||
|
||||
//
|
||||
|
||||
light.shadowCameraNear = this.shadowCameraNear;
|
||||
light.shadowCameraFar = this.shadowCameraFar;
|
||||
light.shadowCameraFov = this.shadowCameraFov;
|
||||
|
||||
light.shadowCameraVisible = this.shadowCameraVisible;
|
||||
|
||||
light.shadowBias = this.shadowBias;
|
||||
light.shadowDarkness = this.shadowDarkness;
|
||||
|
||||
light.shadowMapWidth = this.shadowMapWidth;
|
||||
light.shadowMapHeight = this.shadowMapHeight;
|
||||
|
||||
return light;
|
||||
|
||||
};
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.BufferGeometryLoader = function ( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
|
||||
|
||||
};
|
||||
|
||||
THREE.BufferGeometryLoader.prototype = {
|
||||
|
||||
constructor: THREE.BufferGeometryLoader,
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var loader = new THREE.XHRLoader();
|
||||
loader.setCrossOrigin( this.crossOrigin );
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
onLoad( scope.parse( JSON.parse( text ) ) );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
setCrossOrigin: function ( value ) {
|
||||
|
||||
this.crossOrigin = value;
|
||||
|
||||
},
|
||||
|
||||
parse: function ( json ) {
|
||||
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
|
||||
var attributes = json.attributes;
|
||||
|
||||
for ( var key in attributes ) {
|
||||
|
||||
var attribute = attributes[ key ];
|
||||
|
||||
geometry.attributes[ key ] = {
|
||||
itemSize: attribute.itemSize,
|
||||
array: new self[ attribute.type ]( attribute.array )
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var offsets = json.offsets;
|
||||
|
||||
if ( offsets !== undefined ) {
|
||||
|
||||
geometry.offsets = JSON.parse( JSON.stringify( offsets ) );
|
||||
|
||||
}
|
||||
|
||||
var boundingSphere = json.boundingSphere;
|
||||
|
||||
if ( boundingSphere !== undefined ) {
|
||||
|
||||
geometry.boundingSphere = new THREE.Sphere(
|
||||
new THREE.Vector3().fromArray( boundingSphere.center !== undefined ? boundingSphere.center : [ 0, 0, 0 ] ),
|
||||
boundingSphere.radius
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
return geometry;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.Cache = function () {
|
||||
|
||||
this.files = {};
|
||||
|
||||
};
|
||||
|
||||
THREE.Cache.prototype = {
|
||||
|
||||
constructor: THREE.Cache,
|
||||
|
||||
add: function ( key, file ) {
|
||||
|
||||
// console.log( 'THREE.Cache', 'Adding key:', key );
|
||||
|
||||
this.files[ key ] = file;
|
||||
|
||||
},
|
||||
|
||||
get: function ( key ) {
|
||||
|
||||
// console.log( 'THREE.Cache', 'Checking key:', key );
|
||||
|
||||
return this.files[ key ];
|
||||
|
||||
},
|
||||
|
||||
remove: function ( key ) {
|
||||
|
||||
delete this.files[ key ];
|
||||
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
|
||||
this.files = {}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.GeometryLoader = function ( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
|
||||
|
||||
};
|
||||
|
||||
THREE.GeometryLoader.prototype = {
|
||||
|
||||
constructor: THREE.GeometryLoader,
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var loader = new THREE.XHRLoader();
|
||||
loader.setCrossOrigin( this.crossOrigin );
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
onLoad( scope.parse( JSON.parse( text ) ) );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
setCrossOrigin: function ( value ) {
|
||||
|
||||
this.crossOrigin = value;
|
||||
|
||||
},
|
||||
|
||||
parse: function ( json ) {
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
geometry.indices = json.indices;
|
||||
geometry.vertices = json.vertices;
|
||||
geometry.normals = json.normals;
|
||||
geometry.uvs = json.uvs;
|
||||
|
||||
var boundingSphere = json.boundingSphere;
|
||||
|
||||
if ( boundingSphere !== undefined ) {
|
||||
|
||||
geometry.boundingSphere = new THREE.Sphere(
|
||||
new THREE.Vector3().fromArray( boundingSphere.center !== undefined ? boundingSphere.center : [ 0, 0, 0 ] ),
|
||||
boundingSphere.radius
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
return geometry;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.ImageLoader = function ( manager ) {
|
||||
|
||||
this.cache = new THREE.Cache();
|
||||
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
|
||||
|
||||
};
|
||||
|
||||
THREE.ImageLoader.prototype = {
|
||||
|
||||
constructor: THREE.ImageLoader,
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var cached = scope.cache.get( url );
|
||||
|
||||
if ( cached !== undefined ) {
|
||||
|
||||
onLoad( cached );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
var image = document.createElement( 'img' );
|
||||
|
||||
if ( onLoad !== undefined ) {
|
||||
|
||||
image.addEventListener( 'load', function ( event ) {
|
||||
|
||||
scope.cache.add( url, this );
|
||||
|
||||
onLoad( this );
|
||||
scope.manager.itemEnd( url );
|
||||
|
||||
}, false );
|
||||
|
||||
}
|
||||
|
||||
if ( onProgress !== undefined ) {
|
||||
|
||||
image.addEventListener( 'progress', function ( event ) {
|
||||
|
||||
onProgress( event );
|
||||
|
||||
}, false );
|
||||
|
||||
}
|
||||
|
||||
if ( onError !== undefined ) {
|
||||
|
||||
image.addEventListener( 'error', function ( event ) {
|
||||
|
||||
onError( event );
|
||||
|
||||
}, false );
|
||||
|
||||
}
|
||||
|
||||
if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
|
||||
|
||||
image.src = url;
|
||||
|
||||
scope.manager.itemStart( url );
|
||||
|
||||
return image;
|
||||
|
||||
},
|
||||
|
||||
setCrossOrigin: function ( value ) {
|
||||
|
||||
this.crossOrigin = value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,544 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.JSONLoader = function ( showStatus ) {
|
||||
|
||||
THREE.Loader.call( this, showStatus );
|
||||
|
||||
this.withCredentials = false;
|
||||
|
||||
};
|
||||
|
||||
THREE.JSONLoader.prototype = Object.create( THREE.Loader.prototype );
|
||||
|
||||
THREE.JSONLoader.prototype.load = function ( url, callback, texturePath ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
// todo: unify load API to for easier SceneLoader use
|
||||
|
||||
texturePath = texturePath && ( typeof texturePath === 'string' ) ? texturePath : this.extractUrlBase( url );
|
||||
|
||||
this.onLoadStart();
|
||||
this.loadAjaxJSON( this, url, callback, texturePath );
|
||||
|
||||
};
|
||||
|
||||
THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, texturePath, callbackProgress ) {
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
var length = 0;
|
||||
|
||||
xhr.onreadystatechange = function () {
|
||||
|
||||
if ( xhr.readyState === xhr.DONE ) {
|
||||
|
||||
if ( xhr.status === 200 || xhr.status === 0 ) {
|
||||
|
||||
if ( xhr.responseText ) {
|
||||
|
||||
var json = JSON.parse( xhr.responseText );
|
||||
|
||||
if ( json.metadata !== undefined && json.metadata.type === 'scene' ) {
|
||||
|
||||
console.error( 'THREE.JSONLoader: "' + url + '" seems to be a Scene. Use THREE.SceneLoader instead.' );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
var result = context.parse( json, texturePath );
|
||||
callback( result.geometry, result.materials );
|
||||
|
||||
} else {
|
||||
|
||||
console.error( 'THREE.JSONLoader: "' + url + '" seems to be unreachable or the file is empty.' );
|
||||
|
||||
}
|
||||
|
||||
// in context of more complex asset initialization
|
||||
// do not block on single failed file
|
||||
// maybe should go even one more level up
|
||||
|
||||
context.onLoadComplete();
|
||||
|
||||
} else {
|
||||
|
||||
console.error( 'THREE.JSONLoader: Couldn\'t load "' + url + '" (' + xhr.status + ')' );
|
||||
|
||||
}
|
||||
|
||||
} else if ( xhr.readyState === xhr.LOADING ) {
|
||||
|
||||
if ( callbackProgress ) {
|
||||
|
||||
if ( length === 0 ) {
|
||||
|
||||
length = xhr.getResponseHeader( 'Content-Length' );
|
||||
|
||||
}
|
||||
|
||||
callbackProgress( { total: length, loaded: xhr.responseText.length } );
|
||||
|
||||
}
|
||||
|
||||
} else if ( xhr.readyState === xhr.HEADERS_RECEIVED ) {
|
||||
|
||||
if ( callbackProgress !== undefined ) {
|
||||
|
||||
length = xhr.getResponseHeader( 'Content-Length' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
xhr.open( 'GET', url, true );
|
||||
xhr.withCredentials = this.withCredentials;
|
||||
xhr.send( null );
|
||||
|
||||
};
|
||||
|
||||
THREE.JSONLoader.prototype.parse = function ( json, texturePath ) {
|
||||
|
||||
var scope = this,
|
||||
geometry = new THREE.Geometry(),
|
||||
scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
|
||||
|
||||
parseModel( scale );
|
||||
|
||||
parseSkin();
|
||||
parseMorphing( scale );
|
||||
|
||||
geometry.computeFaceNormals();
|
||||
geometry.computeBoundingSphere();
|
||||
|
||||
function parseModel( scale ) {
|
||||
|
||||
function isBitSet( value, position ) {
|
||||
|
||||
return value & ( 1 << position );
|
||||
|
||||
}
|
||||
|
||||
var i, j, fi,
|
||||
|
||||
offset, zLength,
|
||||
|
||||
colorIndex, normalIndex, uvIndex, materialIndex,
|
||||
|
||||
type,
|
||||
isQuad,
|
||||
hasMaterial,
|
||||
hasFaceVertexUv,
|
||||
hasFaceNormal, hasFaceVertexNormal,
|
||||
hasFaceColor, hasFaceVertexColor,
|
||||
|
||||
vertex, face, faceA, faceB, color, hex, normal,
|
||||
|
||||
uvLayer, uv, u, v,
|
||||
|
||||
faces = json.faces,
|
||||
vertices = json.vertices,
|
||||
normals = json.normals,
|
||||
colors = json.colors,
|
||||
|
||||
nUvLayers = 0;
|
||||
|
||||
if ( json.uvs !== undefined ) {
|
||||
|
||||
// disregard empty arrays
|
||||
|
||||
for ( i = 0; i < json.uvs.length; i ++ ) {
|
||||
|
||||
if ( json.uvs[ i ].length ) nUvLayers ++;
|
||||
|
||||
}
|
||||
|
||||
for ( i = 0; i < nUvLayers; i ++ ) {
|
||||
|
||||
geometry.faceVertexUvs[ i ] = [];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
zLength = vertices.length;
|
||||
|
||||
while ( offset < zLength ) {
|
||||
|
||||
vertex = new THREE.Vector3();
|
||||
|
||||
vertex.x = vertices[ offset ++ ] * scale;
|
||||
vertex.y = vertices[ offset ++ ] * scale;
|
||||
vertex.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 );
|
||||
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, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
|
||||
|
||||
if ( isQuad ) {
|
||||
|
||||
faceA = new THREE.Face3();
|
||||
faceA.a = faces[ offset ];
|
||||
faceA.b = faces[ offset + 1 ];
|
||||
faceA.c = faces[ offset + 3 ];
|
||||
|
||||
faceB = new THREE.Face3();
|
||||
faceB.a = faces[ offset + 1 ];
|
||||
faceB.b = faces[ offset + 2 ];
|
||||
faceB.c = faces[ offset + 3 ];
|
||||
|
||||
offset += 4;
|
||||
|
||||
if ( hasMaterial ) {
|
||||
|
||||
materialIndex = faces[ offset ++ ];
|
||||
faceA.materialIndex = materialIndex;
|
||||
faceB.materialIndex = materialIndex;
|
||||
|
||||
}
|
||||
|
||||
// to get face <=> uv index correspondence
|
||||
|
||||
fi = geometry.faces.length;
|
||||
|
||||
if ( hasFaceVertexUv ) {
|
||||
|
||||
for ( i = 0; i < nUvLayers; i ++ ) {
|
||||
|
||||
uvLayer = json.uvs[ i ];
|
||||
|
||||
geometry.faceVertexUvs[ i ][ fi ] = [];
|
||||
geometry.faceVertexUvs[ i ][ fi + 1 ] = []
|
||||
|
||||
for ( j = 0; j < 4; j ++ ) {
|
||||
|
||||
uvIndex = faces[ offset ++ ];
|
||||
|
||||
u = uvLayer[ uvIndex * 2 ];
|
||||
v = uvLayer[ uvIndex * 2 + 1 ];
|
||||
|
||||
uv = new THREE.Vector2( u, v );
|
||||
|
||||
if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
|
||||
if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( hasFaceNormal ) {
|
||||
|
||||
normalIndex = faces[ offset ++ ] * 3;
|
||||
|
||||
faceA.normal.set(
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ]
|
||||
);
|
||||
|
||||
faceB.normal.copy( faceA.normal );
|
||||
|
||||
}
|
||||
|
||||
if ( hasFaceVertexNormal ) {
|
||||
|
||||
for ( i = 0; i < 4; i ++ ) {
|
||||
|
||||
normalIndex = faces[ offset ++ ] * 3;
|
||||
|
||||
normal = new THREE.Vector3(
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ]
|
||||
);
|
||||
|
||||
|
||||
if ( i !== 2 ) faceA.vertexNormals.push( normal );
|
||||
if ( i !== 0 ) faceB.vertexNormals.push( normal );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ( hasFaceColor ) {
|
||||
|
||||
colorIndex = faces[ offset ++ ];
|
||||
hex = colors[ colorIndex ];
|
||||
|
||||
faceA.color.setHex( hex );
|
||||
faceB.color.setHex( hex );
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ( hasFaceVertexColor ) {
|
||||
|
||||
for ( i = 0; i < 4; i ++ ) {
|
||||
|
||||
colorIndex = faces[ offset ++ ];
|
||||
hex = colors[ colorIndex ];
|
||||
|
||||
if ( i !== 2 ) faceA.vertexColors.push( new THREE.Color( hex ) );
|
||||
if ( i !== 0 ) faceB.vertexColors.push( new THREE.Color( hex ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.faces.push( faceA );
|
||||
geometry.faces.push( faceB );
|
||||
|
||||
} else {
|
||||
|
||||
face = new THREE.Face3();
|
||||
face.a = faces[ offset ++ ];
|
||||
face.b = faces[ offset ++ ];
|
||||
face.c = faces[ offset ++ ];
|
||||
|
||||
if ( hasMaterial ) {
|
||||
|
||||
materialIndex = faces[ offset ++ ];
|
||||
face.materialIndex = materialIndex;
|
||||
|
||||
}
|
||||
|
||||
// to get face <=> uv index correspondence
|
||||
|
||||
fi = geometry.faces.length;
|
||||
|
||||
if ( hasFaceVertexUv ) {
|
||||
|
||||
for ( i = 0; i < nUvLayers; i ++ ) {
|
||||
|
||||
uvLayer = json.uvs[ i ];
|
||||
|
||||
geometry.faceVertexUvs[ i ][ fi ] = [];
|
||||
|
||||
for ( j = 0; j < 3; j ++ ) {
|
||||
|
||||
uvIndex = faces[ offset ++ ];
|
||||
|
||||
u = uvLayer[ uvIndex * 2 ];
|
||||
v = uvLayer[ uvIndex * 2 + 1 ];
|
||||
|
||||
uv = new THREE.Vector2( u, v );
|
||||
|
||||
geometry.faceVertexUvs[ i ][ fi ].push( uv );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( hasFaceNormal ) {
|
||||
|
||||
normalIndex = faces[ offset ++ ] * 3;
|
||||
|
||||
face.normal.set(
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
if ( hasFaceVertexNormal ) {
|
||||
|
||||
for ( i = 0; i < 3; i ++ ) {
|
||||
|
||||
normalIndex = faces[ offset ++ ] * 3;
|
||||
|
||||
normal = new THREE.Vector3(
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ]
|
||||
);
|
||||
|
||||
face.vertexNormals.push( normal );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ( hasFaceColor ) {
|
||||
|
||||
colorIndex = faces[ offset ++ ];
|
||||
face.color.setHex( colors[ colorIndex ] );
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ( hasFaceVertexColor ) {
|
||||
|
||||
for ( i = 0; i < 3; i ++ ) {
|
||||
|
||||
colorIndex = faces[ offset ++ ];
|
||||
face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.faces.push( face );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function parseSkin() {
|
||||
var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
|
||||
|
||||
if ( json.skinWeights ) {
|
||||
|
||||
for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
|
||||
|
||||
var x = json.skinWeights[ i ];
|
||||
var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
|
||||
var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
|
||||
var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
|
||||
|
||||
geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( json.skinIndices ) {
|
||||
|
||||
for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
|
||||
|
||||
var a = json.skinIndices[ i ];
|
||||
var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
|
||||
var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
|
||||
var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
|
||||
|
||||
geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.bones = json.bones;
|
||||
|
||||
if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
|
||||
|
||||
console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
|
||||
geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// could change this to json.animations[0] or remove completely
|
||||
|
||||
geometry.animation = json.animation;
|
||||
geometry.animations = json.animations;
|
||||
|
||||
};
|
||||
|
||||
function parseMorphing( scale ) {
|
||||
|
||||
if ( json.morphTargets !== undefined ) {
|
||||
|
||||
var i, l, v, vl, 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 ) {
|
||||
|
||||
var vertex = new THREE.Vector3();
|
||||
vertex.x = srcVertices[ v ] * scale;
|
||||
vertex.y = srcVertices[ v + 1 ] * scale;
|
||||
vertex.z = srcVertices[ v + 2 ] * scale;
|
||||
|
||||
dstVertices.push( vertex );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if ( json.materials === undefined || json.materials.length === 0 ) {
|
||||
|
||||
return { geometry: geometry };
|
||||
|
||||
} else {
|
||||
|
||||
var materials = this.initMaterials( json.materials, texturePath );
|
||||
|
||||
if ( this.needsTangents( materials ) ) {
|
||||
|
||||
geometry.computeTangents();
|
||||
|
||||
}
|
||||
|
||||
return { geometry: geometry, materials: materials };
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,477 +0,0 @@
|
|||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
THREE.Loader = function ( showStatus ) {
|
||||
|
||||
this.showStatus = showStatus;
|
||||
this.statusDomElement = showStatus ? THREE.Loader.prototype.addStatusElement() : null;
|
||||
|
||||
this.imageLoader = new THREE.ImageLoader();
|
||||
|
||||
this.onLoadStart = function () {};
|
||||
this.onLoadProgress = function () {};
|
||||
this.onLoadComplete = function () {};
|
||||
|
||||
};
|
||||
|
||||
THREE.Loader.prototype = {
|
||||
|
||||
constructor: THREE.Loader,
|
||||
|
||||
crossOrigin: undefined,
|
||||
|
||||
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 / 1024 ).toFixed( 2 ) + ' KB';
|
||||
|
||||
}
|
||||
|
||||
this.statusDomElement.innerHTML = message;
|
||||
|
||||
},
|
||||
|
||||
extractUrlBase: function ( url ) {
|
||||
|
||||
var parts = url.split( '/' );
|
||||
|
||||
if ( parts.length === 1 ) return './';
|
||||
|
||||
parts.pop();
|
||||
|
||||
return parts.join( '/' ) + '/';
|
||||
|
||||
},
|
||||
|
||||
initMaterials: function ( materials, texturePath ) {
|
||||
|
||||
var array = [];
|
||||
|
||||
for ( var i = 0; i < materials.length; ++ i ) {
|
||||
|
||||
array[ i ] = this.createMaterial( materials[ i ], texturePath );
|
||||
|
||||
}
|
||||
|
||||
return array;
|
||||
|
||||
},
|
||||
|
||||
needsTangents: function ( materials ) {
|
||||
|
||||
for ( var i = 0, il = materials.length; i < il; i ++ ) {
|
||||
|
||||
var m = materials[ i ];
|
||||
|
||||
if ( m instanceof THREE.ShaderMaterial ) return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
},
|
||||
|
||||
createMaterial: function ( m, texturePath ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
function nearest_pow2( n ) {
|
||||
|
||||
var l = Math.log( n ) / Math.LN2;
|
||||
return Math.pow( 2, Math.round( l ) );
|
||||
|
||||
}
|
||||
|
||||
function create_texture( where, name, sourceFile, repeat, offset, wrap, anisotropy ) {
|
||||
|
||||
var fullPath = texturePath + sourceFile;
|
||||
|
||||
var texture;
|
||||
|
||||
var loader = THREE.Loader.Handlers.get( fullPath );
|
||||
|
||||
if ( loader !== null ) {
|
||||
|
||||
texture = loader.load( fullPath );
|
||||
|
||||
} else {
|
||||
|
||||
texture = new THREE.Texture();
|
||||
|
||||
loader = scope.imageLoader;
|
||||
loader.crossOrigin = scope.crossOrigin;
|
||||
loader.load( fullPath, function ( image ) {
|
||||
|
||||
if ( THREE.Math.isPowerOfTwo( image.width ) === false ||
|
||||
THREE.Math.isPowerOfTwo( image.height ) === false ) {
|
||||
|
||||
var width = nearest_pow2( image.width );
|
||||
var height = nearest_pow2( image.height );
|
||||
|
||||
var canvas = document.createElement( 'canvas' );
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
var context = canvas.getContext( '2d' );
|
||||
context.drawImage( image, 0, 0, width, height );
|
||||
|
||||
texture.image = canvas;
|
||||
|
||||
} else {
|
||||
|
||||
texture.image = image;
|
||||
|
||||
}
|
||||
|
||||
texture.needsUpdate = true;
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
texture.sourceFile = sourceFile;
|
||||
|
||||
if ( repeat ) {
|
||||
|
||||
texture.repeat.set( repeat[ 0 ], repeat[ 1 ] );
|
||||
|
||||
if ( repeat[ 0 ] !== 1 ) texture.wrapS = THREE.RepeatWrapping;
|
||||
if ( repeat[ 1 ] !== 1 ) texture.wrapT = THREE.RepeatWrapping;
|
||||
|
||||
}
|
||||
|
||||
if ( offset ) {
|
||||
|
||||
texture.offset.set( offset[ 0 ], offset[ 1 ] );
|
||||
|
||||
}
|
||||
|
||||
if ( wrap ) {
|
||||
|
||||
var wrapMap = {
|
||||
'repeat': THREE.RepeatWrapping,
|
||||
'mirror': THREE.MirroredRepeatWrapping
|
||||
}
|
||||
|
||||
if ( wrapMap[ wrap[ 0 ] ] !== undefined ) texture.wrapS = wrapMap[ wrap[ 0 ] ];
|
||||
if ( wrapMap[ wrap[ 1 ] ] !== undefined ) texture.wrapT = wrapMap[ wrap[ 1 ] ];
|
||||
|
||||
}
|
||||
|
||||
if ( anisotropy ) {
|
||||
|
||||
texture.anisotropy = anisotropy;
|
||||
|
||||
}
|
||||
|
||||
where[ name ] = texture;
|
||||
|
||||
}
|
||||
|
||||
function rgb2hex( rgb ) {
|
||||
|
||||
return ( rgb[ 0 ] * 255 << 16 ) + ( rgb[ 1 ] * 255 << 8 ) + rgb[ 2 ] * 255;
|
||||
|
||||
}
|
||||
|
||||
// defaults
|
||||
|
||||
var mtype = 'MeshLambertMaterial';
|
||||
var mpars = { color: 0xeeeeee, opacity: 1.0, map: null, lightMap: null, normalMap: null, bumpMap: null, wireframe: false };
|
||||
|
||||
// parameters from model file
|
||||
|
||||
if ( m.shading ) {
|
||||
|
||||
var shading = m.shading.toLowerCase();
|
||||
|
||||
if ( shading === 'phong' ) mtype = 'MeshPhongMaterial';
|
||||
else if ( shading === 'basic' ) mtype = 'MeshBasicMaterial';
|
||||
|
||||
}
|
||||
|
||||
if ( m.blending !== undefined && THREE[ m.blending ] !== undefined ) {
|
||||
|
||||
mpars.blending = THREE[ m.blending ];
|
||||
|
||||
}
|
||||
|
||||
if ( m.transparent !== undefined || m.opacity < 1.0 ) {
|
||||
|
||||
mpars.transparent = m.transparent;
|
||||
|
||||
}
|
||||
|
||||
if ( m.depthTest !== undefined ) {
|
||||
|
||||
mpars.depthTest = m.depthTest;
|
||||
|
||||
}
|
||||
|
||||
if ( m.depthWrite !== undefined ) {
|
||||
|
||||
mpars.depthWrite = m.depthWrite;
|
||||
|
||||
}
|
||||
|
||||
if ( m.visible !== undefined ) {
|
||||
|
||||
mpars.visible = m.visible;
|
||||
|
||||
}
|
||||
|
||||
if ( m.flipSided !== undefined ) {
|
||||
|
||||
mpars.side = THREE.BackSide;
|
||||
|
||||
}
|
||||
|
||||
if ( m.doubleSided !== undefined ) {
|
||||
|
||||
mpars.side = THREE.DoubleSide;
|
||||
|
||||
}
|
||||
|
||||
if ( m.wireframe !== undefined ) {
|
||||
|
||||
mpars.wireframe = m.wireframe;
|
||||
|
||||
}
|
||||
|
||||
if ( m.vertexColors !== undefined ) {
|
||||
|
||||
if ( m.vertexColors === 'face' ) {
|
||||
|
||||
mpars.vertexColors = THREE.FaceColors;
|
||||
|
||||
} else if ( m.vertexColors ) {
|
||||
|
||||
mpars.vertexColors = THREE.VertexColors;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// colors
|
||||
|
||||
if ( m.colorDiffuse ) {
|
||||
|
||||
mpars.color = rgb2hex( m.colorDiffuse );
|
||||
|
||||
} else if ( m.DbgColor ) {
|
||||
|
||||
mpars.color = m.DbgColor;
|
||||
|
||||
}
|
||||
|
||||
if ( m.colorSpecular ) {
|
||||
|
||||
mpars.specular = rgb2hex( m.colorSpecular );
|
||||
|
||||
}
|
||||
|
||||
if ( m.colorAmbient ) {
|
||||
|
||||
mpars.ambient = rgb2hex( m.colorAmbient );
|
||||
|
||||
}
|
||||
|
||||
if ( m.colorEmissive ) {
|
||||
|
||||
mpars.emissive = rgb2hex( m.colorEmissive );
|
||||
|
||||
}
|
||||
|
||||
// modifiers
|
||||
|
||||
if ( m.transparency ) {
|
||||
|
||||
mpars.opacity = m.transparency;
|
||||
|
||||
}
|
||||
|
||||
if ( m.specularCoef ) {
|
||||
|
||||
mpars.shininess = m.specularCoef;
|
||||
|
||||
}
|
||||
|
||||
// textures
|
||||
|
||||
if ( m.mapDiffuse && texturePath ) {
|
||||
|
||||
create_texture( mpars, 'map', m.mapDiffuse, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
|
||||
|
||||
}
|
||||
|
||||
if ( m.mapLight && texturePath ) {
|
||||
|
||||
create_texture( mpars, 'lightMap', m.mapLight, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
|
||||
|
||||
}
|
||||
|
||||
if ( m.mapBump && texturePath ) {
|
||||
|
||||
create_texture( mpars, 'bumpMap', m.mapBump, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
|
||||
|
||||
}
|
||||
|
||||
if ( m.mapNormal && texturePath ) {
|
||||
|
||||
create_texture( mpars, 'normalMap', m.mapNormal, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
|
||||
|
||||
}
|
||||
|
||||
if ( m.mapSpecular && texturePath ) {
|
||||
|
||||
create_texture( mpars, 'specularMap', m.mapSpecular, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
|
||||
|
||||
}
|
||||
|
||||
if ( m.mapAlpha && texturePath ) {
|
||||
|
||||
create_texture( mpars, 'alphaMap', m.mapAlpha, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if ( m.mapBumpScale ) {
|
||||
|
||||
mpars.bumpScale = m.mapBumpScale;
|
||||
|
||||
}
|
||||
|
||||
// special case for normal mapped material
|
||||
|
||||
if ( m.mapNormal ) {
|
||||
|
||||
var shader = THREE.ShaderLib[ 'normalmap' ];
|
||||
var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
|
||||
|
||||
uniforms[ 'tNormal' ].value = mpars.normalMap;
|
||||
|
||||
if ( m.mapNormalFactor ) {
|
||||
|
||||
uniforms[ 'uNormalScale' ].value.set( m.mapNormalFactor, m.mapNormalFactor );
|
||||
|
||||
}
|
||||
|
||||
if ( mpars.map ) {
|
||||
|
||||
uniforms[ 'tDiffuse' ].value = mpars.map;
|
||||
uniforms[ 'enableDiffuse' ].value = true;
|
||||
|
||||
}
|
||||
|
||||
if ( mpars.specularMap ) {
|
||||
|
||||
uniforms[ 'tSpecular' ].value = mpars.specularMap;
|
||||
uniforms[ 'enableSpecular' ].value = true;
|
||||
|
||||
}
|
||||
|
||||
if ( mpars.lightMap ) {
|
||||
|
||||
uniforms[ 'tAO' ].value = mpars.lightMap;
|
||||
uniforms[ 'enableAO' ].value = true;
|
||||
|
||||
}
|
||||
|
||||
// for the moment don't handle displacement texture
|
||||
|
||||
uniforms[ 'diffuse' ].value.setHex( mpars.color );
|
||||
uniforms[ 'specular' ].value.setHex( mpars.specular );
|
||||
uniforms[ 'ambient' ].value.setHex( mpars.ambient );
|
||||
|
||||
uniforms[ 'shininess' ].value = mpars.shininess;
|
||||
|
||||
if ( mpars.opacity !== undefined ) {
|
||||
|
||||
uniforms[ 'opacity' ].value = mpars.opacity;
|
||||
|
||||
}
|
||||
|
||||
var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: true };
|
||||
var material = new THREE.ShaderMaterial( parameters );
|
||||
|
||||
if ( mpars.transparent ) {
|
||||
|
||||
material.transparent = true;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
var material = new THREE[ mtype ]( mpars );
|
||||
|
||||
}
|
||||
|
||||
if ( m.DbgName !== undefined ) material.name = m.DbgName;
|
||||
|
||||
return material;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.Loader.Handlers = {
|
||||
|
||||
handlers: [],
|
||||
|
||||
add: function ( regex, loader ) {
|
||||
|
||||
this.handlers.push( regex, loader );
|
||||
|
||||
},
|
||||
|
||||
get: function ( file ) {
|
||||
|
||||
for ( var i = 0, l = this.handlers.length; i < l; i += 2 ) {
|
||||
|
||||
var regex = this.handlers[ i ];
|
||||
var loader = this.handlers[ i + 1 ];
|
||||
|
||||
if ( regex.test( file ) ) {
|
||||
|
||||
return loader;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.LoadingManager = function ( onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var loaded = 0, total = 0;
|
||||
|
||||
this.onLoad = onLoad;
|
||||
this.onProgress = onProgress;
|
||||
this.onError = onError;
|
||||
|
||||
this.itemStart = function ( url ) {
|
||||
|
||||
total ++;
|
||||
|
||||
};
|
||||
|
||||
this.itemEnd = function ( url ) {
|
||||
|
||||
loaded ++;
|
||||
|
||||
if ( scope.onProgress !== undefined ) {
|
||||
|
||||
scope.onProgress( url, loaded, total );
|
||||
|
||||
}
|
||||
|
||||
if ( loaded === total && scope.onLoad !== undefined ) {
|
||||
|
||||
scope.onLoad();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
THREE.DefaultLoadingManager = new THREE.LoadingManager();
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
THREE.MaterialLoader = function ( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
|
||||
|
||||
};
|
||||
|
||||
THREE.MaterialLoader.prototype = {
|
||||
|
||||
constructor: THREE.MaterialLoader,
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var loader = new THREE.XHRLoader();
|
||||
loader.setCrossOrigin( this.crossOrigin );
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
onLoad( scope.parse( JSON.parse( text ) ) );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
setCrossOrigin: function ( value ) {
|
||||
|
||||
this.crossOrigin = value;
|
||||
|
||||
},
|
||||
|
||||
parse: function ( json ) {
|
||||
|
||||
var material = new THREE[ json.type ];
|
||||
|
||||
if ( json.color !== undefined ) material.color.setHex( json.color );
|
||||
if ( json.ambient !== undefined ) material.ambient.setHex( json.ambient );
|
||||
if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive );
|
||||
if ( json.specular !== undefined ) material.specular.setHex( json.specular );
|
||||
if ( json.shininess !== undefined ) material.shininess = json.shininess;
|
||||
if ( json.uniforms !== undefined ) material.uniforms = json.uniforms;
|
||||
if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
|
||||
if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
|
||||
if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors;
|
||||
if ( json.blending !== undefined ) material.blending = json.blending;
|
||||
if ( json.side !== undefined ) material.side = json.side;
|
||||
if ( json.opacity !== undefined ) material.opacity = json.opacity;
|
||||
if ( json.transparent !== undefined ) material.transparent = json.transparent;
|
||||
if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
|
||||
|
||||
if ( json.materials !== undefined ) {
|
||||
|
||||
for ( var i = 0, l = json.materials.length; i < l; i ++ ) {
|
||||
|
||||
material.materials.push( this.parse( json.materials[ i ] ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return material;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue