123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954 |
- /**
- * @author arodic / https://github.com/arodic
- */
- //"use strict";
- THREE.TransformControls = function ( camera, domElement, doc ) {
- // TODO: Make non-uniform scale and rotate play nice in hierarchies
- // TODO: ADD RXYZ contol
- this.camera = camera;
- this.domElement = ( domElement !== undefined ) ? domElement : document;
- this.document = ( doc !== undefined ) ? doc : document;
- this.object = undefined;
- this.active = false;
- this.hovered = false;
- this.mode = 'translate';
- this.space = 'local';
- this.scale = 1;
- this.snapDist = null;
- this.modifierAxis = new THREE.Vector3( 1, 1, 1 );
- this.gizmo = new THREE.Object3D();
- var scope = this;
- var changeEvent = { type: 'change' };
- var showPickers = false; // debug
- var ray = new THREE.Raycaster();
- var projector = new THREE.Projector();
- var pointerVector = new THREE.Vector3();
- var point = new THREE.Vector3();
- var offset = new THREE.Vector3();
- var rotation = new THREE.Vector3();
- var offsetRotation = new THREE.Vector3();
- var scale = 1;
- var lookAtMatrix = new THREE.Matrix4();
- var eye = new THREE.Vector3()
- var tempMatrix = new THREE.Matrix4();
- var tempVector = new THREE.Vector3();
- var tempQuaternion = new THREE.Quaternion();
- var unitX = new THREE.Vector3( 1, 0, 0 );
- var unitY = new THREE.Vector3( 0, 1, 0 );
- var unitZ = new THREE.Vector3( 0, 0, 1 );
- var quaternionXYZ = new THREE.Quaternion();
- var quaternionX = new THREE.Quaternion();
- var quaternionY = new THREE.Quaternion();
- var quaternionZ = new THREE.Quaternion();
- var quaternionE = new THREE.Quaternion();
- var oldPosition = new THREE.Vector3();
- var oldScale = new THREE.Vector3();
- var oldRotationMatrix = new THREE.Matrix4();
- var parentRotationMatrix = new THREE.Matrix4();
- var parentScale = new THREE.Vector3();
- var worldPosition = new THREE.Vector3();
- var worldRotation = new THREE.Vector3();
- var worldRotationMatrix = new THREE.Matrix4();
- var camPosition = new THREE.Vector3();
- var camRotation = new THREE.Vector3();
- var displayAxes = {};
- var pickerAxes = {};
- var intersectionPlanes = {};
- var intersectionPlaneList = ['XY','YZ','XZ','XYZE']; // E
- var currentPlane = 'XY';
- // intersection planes
- {
- var planes = new THREE.Object3D();
- this.gizmo.add(planes);
- for ( var i in intersectionPlaneList ){
- intersectionPlanes[intersectionPlaneList[i]] = new THREE.Mesh( new THREE.PlaneGeometry( 500, 500 ) );
- intersectionPlanes[intersectionPlaneList[i]].material.side = THREE.DoubleSide;
- intersectionPlanes[intersectionPlaneList[i]].visible = false;
- planes.add(intersectionPlanes[intersectionPlaneList[i]]);
- }
- intersectionPlanes['YZ'].rotation.set( 0, Math.PI/2, 0 );
- intersectionPlanes['XZ'].rotation.set( -Math.PI/2, 0, 0 );
- bakeTransformations(intersectionPlanes['YZ']);
- bakeTransformations(intersectionPlanes['XZ']);
- }
- // gizmo geometry
- {
- displayAxes["translate"] = new THREE.Object3D();
- displayAxes["rotate"] = new THREE.Object3D();
- displayAxes["scale"] = new THREE.Object3D();
- this.gizmo.add( displayAxes["translate"] );
- this.gizmo.add( displayAxes["rotate"] );
- this.gizmo.add( displayAxes["scale"] );
- pickerAxes["translate"] = new THREE.Object3D();
- pickerAxes["rotate"] = new THREE.Object3D();
- pickerAxes["scale"] = new THREE.Object3D();
- this.gizmo.add( pickerAxes["translate"] );
- this.gizmo.add( pickerAxes["rotate"] );
- this.gizmo.add( pickerAxes["scale"] );
- var HandleMaterial = function ( color, opacity ) {
- var material = new THREE.MeshBasicMaterial();
- material.color = color;
- material.side = THREE.DoubleSide;
- material.depthTest = false;
- material.depthWrite = false;
- material.opacity = opacity !== undefined ? opacity : 1;
- material.transparent = true;
- return material;
- }
- var LineMaterial = function ( color, opacity ) {
- var material = new THREE.LineBasicMaterial();
- material.color = color;
- material.depthTest = false;
- material.depthWrite = false;
- material.opacity = opacity !== undefined ? opacity : 1;
- material.transparent = true;
- return material;
- }
- // materials by color
- var white = new THREE.Color( 0xffffff );
- var gray = new THREE.Color( 0x808080 );
- var red = new THREE.Color( 0xff0000 );
- var green = new THREE.Color( 0x00ff00 );
- var blue = new THREE.Color( 0x0000ff );
- var cyan = new THREE.Color( 0x00ffff );
- var magenta = new THREE.Color( 0xff00ff );
- var yellow = new THREE.Color( 0xffff00 );
- var geometry, mesh;
- // Line axes
- geometry = new THREE.Geometry();
- geometry.vertices.push(
- new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ),
- new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 1, 0 ),
- new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 1 )
- );
- geometry.colors.push(
- red, red, green, green, blue, blue
- );
- material = new THREE.LineBasicMaterial( {
- vertexColors: THREE.VertexColors,
- depthTest: false,
- depthWrite: false,
- transparent: true
- } );
- mesh = new THREE.Line( geometry, material, THREE.LinePieces );
- displayAxes['translate'].add( mesh );
- displayAxes['scale'].add( mesh.clone() );
- // Translate handles
- mesh = new THREE.Mesh( new THREE.OctahedronGeometry( 0.1, 0 ), HandleMaterial( white, 0.25 ) );
- mesh.name = 'TXYZ';
- displayAxes['translate'].add( mesh );
- pickerAxes['translate'].add( mesh.clone() );
- geometry = new THREE.PlaneGeometry( 0.3, 0.3 );
- mesh = new THREE.Mesh( geometry, HandleMaterial( yellow, 0.25 ) );
- mesh.position.set( 0.15, 0.15, 0 );
- bakeTransformations( mesh );
- mesh.name = 'TXY';
- displayAxes['translate'].add( mesh );
- pickerAxes['translate'].add( mesh.clone() );
- mesh = new THREE.Mesh( geometry, HandleMaterial( cyan, 0.25 ) );
- mesh.position.set( 0, 0.15, 0.15 );
- mesh.rotation.y = Math.PI/2;
- bakeTransformations( mesh );
- mesh.name = 'TYZ';
- displayAxes['translate'].add( mesh );
- pickerAxes['translate'].add( mesh.clone() );
- mesh = new THREE.Mesh( geometry, HandleMaterial( magenta, 0.25 ) );
- mesh.position.set( 0.15, 0, 0.15 );
- mesh.rotation.x = Math.PI/2;
- bakeTransformations( mesh );
- mesh.name = 'TXZ';
- displayAxes['translate'].add( mesh );
- pickerAxes['translate'].add( mesh.clone() );
- geometry = new THREE.CylinderGeometry( 0, 0.05, 0.2, 4, 1, true );
- mesh = new THREE.Mesh( geometry, HandleMaterial( red ) );
- mesh.position.x = 1.1;
- mesh.rotation.z = -Math.PI/2;
- bakeTransformations( mesh );
- mesh.name = 'TX';
- displayAxes['translate'].add( mesh );
- mesh = new THREE.Mesh( geometry, HandleMaterial( green ) );
- mesh.position.y = 1.1;
- bakeTransformations( mesh );
- mesh.name = 'TY';
- displayAxes['translate'].add( mesh );
- mesh = new THREE.Mesh( geometry, HandleMaterial( blue ) );
- mesh.position.z = 1.1;
- mesh.rotation.x = Math.PI/2;
- bakeTransformations( mesh );
- mesh.name = 'TZ';
- displayAxes['translate'].add( mesh );
- geometry = new THREE.CylinderGeometry( 0.2, 0.1, 0.8, 4, 1, false );
- mesh = new THREE.Mesh( geometry, HandleMaterial( red ) );
- mesh.position.x = 0.7;
- mesh.rotation.z = -Math.PI/2;
- bakeTransformations( mesh );
- mesh.name = 'TX';
- pickerAxes['translate'].add( mesh );
- mesh = new THREE.Mesh( geometry, HandleMaterial( green ) );
- mesh.position.y = 0.7;
- bakeTransformations( mesh );
- mesh.name = 'TY';
- pickerAxes['translate'].add( mesh );
- mesh = new THREE.Mesh( geometry, HandleMaterial( blue ) );
- mesh.position.z = 0.7;
- mesh.rotation.x = Math.PI/2;
- bakeTransformations( mesh );
- mesh.name = 'TZ';
- pickerAxes['translate'].add( mesh );
- // scale manipulators
- geometry = new THREE.CubeGeometry( 0.125, 0.125, 0.125 );
- mesh = new THREE.Mesh( geometry, HandleMaterial( white, 0.25 ) );
- mesh.name = 'SXYZ';
- displayAxes['scale'].add( mesh );
- pickerAxes['scale'].add( mesh.clone() );
- mesh = new THREE.Mesh( geometry, HandleMaterial( red ) );
- mesh.position.set( 1.05, 0, 0 );
- bakeTransformations( mesh );
- mesh.name = 'SX';
- displayAxes['scale'].add( mesh );
- pickerAxes['scale'].add( mesh.clone() );
- mesh = new THREE.Mesh( geometry, HandleMaterial( green ) );
- mesh.position.set( 0, 1.05, 0 );
- bakeTransformations( mesh );
- mesh.name = 'SY';
- displayAxes['scale'].add( mesh );
- pickerAxes['scale'].add( mesh.clone() );
- mesh = new THREE.Mesh( geometry, HandleMaterial( blue ) );
- mesh.position.set( 0, 0, 1.05 );
- bakeTransformations( mesh );
- mesh.name = 'SZ';
- displayAxes['scale'].add( mesh );
- pickerAxes['scale'].add( mesh.clone() );
- // rotate manipulators
- var Circle = function ( radius, facing, arc ) {
- geometry = new THREE.Geometry();
- arc = arc ? arc : 1;
- for ( var i = 0; i <= 64 * arc; ++i ) {
- if ( facing == 'x' ) geometry.vertices.push( new THREE.Vector3( 0, Math.cos( i / 32 * Math.PI ), Math.sin( i / 32 * Math.PI ) ).multiplyScalar(radius) );
- if ( facing == 'y' ) geometry.vertices.push( new THREE.Vector3( Math.cos( i / 32 * Math.PI ), 0, Math.sin( i / 32 * Math.PI ) ).multiplyScalar(radius) );
- if ( facing == 'z' ) geometry.vertices.push( new THREE.Vector3( Math.sin( i / 32 * Math.PI ), Math.cos( i / 32 * Math.PI ), 0 ).multiplyScalar(radius) );
- }
- return geometry;
- }
- mesh = new THREE.Line( Circle( 1, 'x', 0.5 ), LineMaterial( red ) );
- mesh.name = 'RX';
- displayAxes['rotate'].add( mesh );
- mesh = new THREE.Line( Circle( 1, 'y', 0.5 ), LineMaterial( green ) );
- mesh.name = 'RY';
- displayAxes['rotate'].add( mesh );
- mesh = new THREE.Line( Circle( 1, 'z', 0.5 ), LineMaterial( blue ) );
- mesh.name = 'RZ';
- displayAxes['rotate'].add( mesh );
- mesh = new THREE.Line( Circle( 1, 'z' ), LineMaterial( gray ) );
- mesh.name = 'RXYZE';
- displayAxes['rotate'].add( mesh );
- mesh = new THREE.Line( Circle( 1.25, 'z' ), LineMaterial( yellow, 0.25 ) );
- mesh.name = 'RE';
- displayAxes['rotate'].add( mesh );
- geometry = new THREE.TorusGeometry( 1, 0.15, 4, 6, Math.PI );
- mesh = new THREE.Mesh( geometry, HandleMaterial( red ) );
- mesh.rotation.z = -Math.PI/2;
- mesh.rotation.y = -Math.PI/2;
- bakeTransformations( mesh );
- mesh.name = 'RX';
- pickerAxes['rotate'].add( mesh );
- mesh = new THREE.Mesh( geometry, HandleMaterial( green ) );
- mesh.rotation.z = Math.PI;
- mesh.rotation.x = -Math.PI/2;
- bakeTransformations( mesh );
- mesh.name = 'RY';
- pickerAxes['rotate'].add( mesh );
- mesh = new THREE.Mesh( geometry, HandleMaterial( blue ) );
- mesh.rotation.z = -Math.PI/2;
- bakeTransformations( mesh );
- mesh.name = 'RZ';
- pickerAxes['rotate'].add( mesh );
- mesh = new THREE.Mesh( new THREE.SphereGeometry( 0.95, 12, 12 ), HandleMaterial( white, 0.25 ) );
- mesh.name = 'RXYZE';
- pickerAxes['rotate'].add( mesh );
- intersectionPlanes['SPHERE'] = new THREE.Mesh( new THREE.SphereGeometry( 0.95, 12, 12 ) );
- intersectionPlanes['SPHERE'].visible = false;
- planes.add(intersectionPlanes['SPHERE']);
- mesh = new THREE.Mesh( new THREE.TorusGeometry( 1.30, 0.15, 4, 12 ), HandleMaterial( yellow, 0.25 ) );
- mesh.name = 'RE';
- pickerAxes['rotate'].add( mesh );
- mesh = null;
- }
- this.attatch = function ( object ) {
- this.object = object;
- this.setMode( scope.mode );
- this.domElement.addEventListener( 'mousedown', onMouseDown, false );
- this.domElement.addEventListener( 'mousemove', onMouseHover, false );
- this.document.addEventListener( 'keydown', onKeyDown, false );
- }
- this.detatch = function ( object ) {
- this.object = undefined;
- this.hide();
- this.domElement.removeEventListener( 'mousedown', onMouseDown, false );
- this.domElement.removeEventListener( 'mousemove', onMouseHover, false );
- this.document.removeEventListener( 'keydown', onKeyDown, false );
- }
- this.update = function () {
- if ( this.object === undefined ) return;
- this.object.updateMatrixWorld();
- worldPosition.getPositionFromMatrix( this.object.matrixWorld );
- worldRotation.setEulerFromRotationMatrix( tempMatrix.extractRotation(this.object.matrixWorld ));
- this.camera.updateMatrixWorld();
- camPosition.getPositionFromMatrix( this.camera.matrixWorld );
- camRotation.setEulerFromRotationMatrix( tempMatrix.extractRotation( this.camera.matrixWorld ));
- scale = worldPosition.distanceTo( camPosition ) / 6 * this.scale;
- this.gizmo.position.copy( worldPosition )
- this.gizmo.scale.set( scale, scale, scale );
- for ( var i in this.gizmo.children ) {
- for ( var j in this.gizmo.children[i].children ) {
- var object = this.gizmo.children[i].children[j];
- var name = object.name;
- if ( name.search('E') != -1 ){
- lookAtMatrix.lookAt( camPosition, worldPosition, tempVector.set( 0, 1, 0 ));
- object.rotation.setEulerFromRotationMatrix( lookAtMatrix );
- } else {
- eye.copy( camPosition ).sub( worldPosition ).normalize();
- if ( this.space == 'local' ) {
- tempQuaternion.setFromEuler( worldRotation );
- if ( name.search('R') != -1 ){
- tempMatrix.makeRotationFromQuaternion( tempQuaternion ).getInverse( tempMatrix );
- eye.applyProjection( tempMatrix );
- if ( name == 'RX' ) {
- quaternionX.setFromAxisAngle( unitX, Math.atan2( -eye.y, eye.z ) );
- tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
- }
- if ( name == 'RY' ) {
- quaternionY.setFromAxisAngle( unitY, Math.atan2( eye.x, eye.z ) );
- tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionY );
- }
- if ( name == 'RZ' ) {
- quaternionZ.setFromAxisAngle( unitZ, Math.atan2( eye.y, eye.x ) );
- tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionZ );
- }
- }
- object.rotation.setEulerFromQuaternion( tempQuaternion );
- } else if ( this.space == 'world' ) {
- object.rotation.set( 0, 0, 0 );
- if ( name == 'RX' ) {
- object.rotation.setX( Math.atan2( -eye.y, eye.z ) );
- }
- if ( name == 'RY' ) {
- object.rotation.setY( Math.atan2( eye.x, eye.z ) );
- }
- if ( name == 'RZ' ) {
- object.rotation.setZ( Math.atan2( eye.y, eye.x ) );
- }
- }
- }
- }
- }
- }
- this.hide = function () {
- for ( var i in displayAxes ) {
- for ( var j in displayAxes[i].children ) {
- displayAxes[i].children[j].visible = false;
- }
- }
- for ( var i in pickerAxes ) {
- for ( var j in pickerAxes[i].children ) {
- pickerAxes[i].children[j].visible = false;
- }
- }
- }
- this.setMode = function ( value ) {
- scope.mode = value;
- this.hide();
- if ( scope.mode == 'scale' ) scope.space = 'local';
- for ( var i in displayAxes[this.mode].children ) {
- displayAxes[this.mode].children[i].visible = true;
- }
- for ( var i in pickerAxes[this.mode].children ) {
- pickerAxes[this.mode].children[i].visible = showPickers;
- }
- scope.update();
- }
- this.setIntersectionPlane = function () {
- eye.copy( camPosition ).sub( worldPosition ).normalize();
- if ( this.space == 'local' ) {
- eye.applyMatrix4( tempMatrix.getInverse( scope.object.matrixWorld ) );
- }
- if ( isActive("X") ) {
- if ( eye.y > eye.z ) currentPlane = 'XZ';
- else currentPlane = 'XY';
- }
- if ( isActive("Y") ) {
- if ( eye.x > eye.z ) currentPlane = 'YZ';
- else currentPlane = 'XY';
- }
- if ( isActive("Z") ) {
- if ( eye.x > eye.y ) currentPlane = 'YZ';
- else currentPlane = 'XZ';
- }
- if ( isActive("XY") ) {
- currentPlane = 'XY';
- }
- if ( isActive("YZ") ) {
- currentPlane = 'YZ';
- }
- if ( isActive("XZ") ) {
- currentPlane = 'XZ';
- }
- if ( isActive("XYZ") || isActive("E") ) {
- currentPlane = 'XYZE';
- }
- if ( isActive("RX") ) {
- currentPlane = 'YZ';
- }
- if ( isActive("RY") ) {
- currentPlane = 'XZ';
- }
- if ( isActive("RZ") ) {
- currentPlane = 'XY';
- }
- if ( isActive("RXYZ") ) {
- currentPlane = 'SPHERE';
- }
- }
- var hovered = null;
- var hoveredColor = new THREE.Color();
- var hoveredOpacity = 1;
- function onMouseHover( event ) {
- event.preventDefault();
- if ( event.button === 0 && scope.active === false ) {
- var intersect = intersectObjects( event, pickerAxes[scope.mode].children );
- if ( intersect ) {
- if ( hovered !== intersect.object ) {
- if ( hovered !== null ) {
- hovered.material.color.copy( hoveredColor );
- hovered.material.opacity = hoveredOpacity;
- }
- hovered = intersect.object;
- hoveredColor.copy( hovered.material.color );
- hoveredOpacity = hovered.material.opacity;
- hovered.material.color.setRGB( 1, 1, 0 );
- hovered.material.opacity = 1;
- scope.dispatchEvent( changeEvent );
- }
- scope.hovered = true;
- } else if ( hovered !== null ) {
- hovered.material.color.copy( hoveredColor );
- hovered.material.opacity = hoveredOpacity;
- hovered = null;
- scope.dispatchEvent( changeEvent );
- scope.hovered = false;
- }
- }
- scope.document.addEventListener( 'mousemove', onMouseMove, false );
- scope.document.addEventListener( 'mouseup', onMouseUp, false );
- };
- function onMouseDown( event ) {
- event.preventDefault();
- if ( event.button === 0 ) {
- var intersect = intersectObjects( event, pickerAxes[scope.mode].children );
- if ( intersect ) {
- scope.active = intersect.object.name;
- scope.update();
- scope.setIntersectionPlane();
- var planeIntersect = intersectObjects( event, [intersectionPlanes[currentPlane]] );
- if ( planeIntersect ) {
- oldPosition.copy( scope.object.position );
- oldScale.copy( scope.object.scale );
- oldRotationMatrix.extractRotation( scope.object.matrix );
- worldRotationMatrix.extractRotation( scope.object.matrixWorld );
- parentRotationMatrix.extractRotation( scope.object.parent.matrixWorld );
- parentScale.getScaleFromMatrix( tempMatrix.getInverse( scope.object.parent.matrixWorld ) );
- offset.copy( planeIntersect.point );
- }
- }
- }
- scope.document.addEventListener( 'mousemove', onMouseMove, false );
- scope.document.addEventListener( 'mouseup', onMouseUp, false );
- };
- function onMouseMove( event ) {
- if ( scope.active ) {
- var planeIntersect = intersectObjects( event, [intersectionPlanes[currentPlane]] );
- if ( planeIntersect ) {
- point.copy( planeIntersect.point );
- if ( ( scope.mode == 'translate' ) && isActive("T") ) {
- point.sub( offset );
- point.multiply(parentScale);
- if ( scope.space == 'local' ) {
- point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
- if ( !(isActive("X")) || scope.modifierAxis.x != 1 ) point.x = 0;
- if ( !(isActive("Y")) || scope.modifierAxis.y != 1 ) point.y = 0;
- if ( !(isActive("Z")) || scope.modifierAxis.z != 1 ) point.z = 0;
- if ( isActive("XYZ") ) point.set( 0, 0, 0 );
- point.applyMatrix4( oldRotationMatrix );
- scope.object.position.copy( oldPosition );
- scope.object.position.add( point );
- }
- if ( scope.space == 'world' || isActive("XYZ") ) {
- if ( !(isActive("X")) || scope.modifierAxis.x != 1 ) point.x = 0;
- if ( !(isActive("Y")) || scope.modifierAxis.y != 1 ) point.y = 0;
- if ( !(isActive("Z")) || scope.modifierAxis.z != 1 ) point.z = 0;
- point.applyMatrix4( tempMatrix.getInverse( parentRotationMatrix ) );
- scope.object.position.copy( oldPosition );
- scope.object.position.add( point );
- if ( scope.snapDist ) {
- if ( isActive("X") ) scope.object.position.x = Math.round( scope.object.position.x / scope.snapDist ) * scope.snapDist;
- if ( isActive("Y") ) scope.object.position.y = Math.round( scope.object.position.y / scope.snapDist ) * scope.snapDist;
- if ( isActive("Z") ) scope.object.position.z = Math.round( scope.object.position.z / scope.snapDist ) * scope.snapDist;
- }
- }
- } else if ( ( scope.mode == 'scale') && isActive("S") ) {
- point.sub( offset );
- point.multiply(parentScale);
- if ( scope.space == 'local' ) {
- if ( isActive("XYZ")) {
- scale = 1 + ( ( point.y ) / 50 );
- scope.object.scale.x = oldScale.x * scale;
- scope.object.scale.y = oldScale.y * scale;
- scope.object.scale.z = oldScale.z * scale;
- } else {
- point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
- if ( !(isActive("X")) || scope.modifierAxis.x != 1 ) point.x = 0;
- if ( !(isActive("Y")) || scope.modifierAxis.y != 1 ) point.y = 0;
- if ( !(isActive("Z")) || scope.modifierAxis.z != 1 ) point.z = 0;
- if ( isActive("X") ) scope.object.scale.x = oldScale.x * ( 1 + point.x / 50 );
- if ( isActive("Y") ) scope.object.scale.y = oldScale.y * ( 1 + point.y / 50 );
- if ( isActive("Z") ) scope.object.scale.z = oldScale.z * ( 1 + point.z / 50 );
- }
- }
- } else if ( ( scope.mode == 'rotate' ) && isActive("R") ) {
- point.sub( worldPosition );
- point.multiply(parentScale);
- tempVector.copy(offset).sub( worldPosition );
- tempVector.multiply(parentScale);
- if ( scope.active == "RE" ) {
- point.applyMatrix4( tempMatrix.getInverse( lookAtMatrix ) );
- tempVector.applyMatrix4( tempMatrix.getInverse( lookAtMatrix ) );
- rotation.set( Math.atan2( point.z, point.y ), Math.atan2( point.x, point.z ), Math.atan2( point.y, point.x ) );
- offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
- tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
- quaternionE.setFromAxisAngle( eye, rotation.z - offsetRotation.z );
- quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
- tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionE );
- tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionXYZ );
- scope.object.rotation.setEulerFromQuaternion( tempQuaternion );
- } else if ( scope.active == "RXYZE" ) {
- quaternionE.setFromEuler( point.clone().cross(tempVector).normalize() ); // rotation axis
- tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
- quaternionX.setFromAxisAngle( quaternionE, - point.clone().angleTo(tempVector) );
- quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
- tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
- tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionXYZ );
- scope.object.rotation.setEulerFromQuaternion( tempQuaternion );
- } else if ( scope.space == 'local' ) {
- point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
- tempVector.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
- rotation.set( Math.atan2( point.z, point.y ), Math.atan2( point.x, point.z ), Math.atan2( point.y, point.x ) );
- offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
- quaternionXYZ.setFromRotationMatrix( oldRotationMatrix );
- quaternionX.setFromAxisAngle( unitX, rotation.x - offsetRotation.x );
- quaternionY.setFromAxisAngle( unitY, rotation.y - offsetRotation.y );
- quaternionZ.setFromAxisAngle( unitZ, rotation.z - offsetRotation.z );
- if ( scope.active == "RX" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionX );
- if ( scope.active == "RY" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionY );
- if ( scope.active == "RZ" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionZ );
- scope.object.rotation.setEulerFromQuaternion( quaternionXYZ );
- } else if ( scope.space == 'world' ) {
- rotation.set( Math.atan2( point.z, point.y ), Math.atan2( point.x, point.z ), Math.atan2( point.y, point.x ) );
- offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
- tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
- quaternionX.setFromAxisAngle( unitX, rotation.x - offsetRotation.x );
- quaternionY.setFromAxisAngle( unitY, rotation.y - offsetRotation.y );
- quaternionZ.setFromAxisAngle( unitZ, rotation.z - offsetRotation.z );
- quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
- if ( scope.active == "RX" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
- if ( scope.active == "RY" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionY );
- if ( scope.active == "RZ" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionZ );
- tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionXYZ );
- scope.object.rotation.setEulerFromQuaternion( tempQuaternion );
- }
- }
- }
- scope.update();
- scope.dispatchEvent( changeEvent );
- }
- }
- function onMouseUp( event ) {
- scope.active = false;
- scope.document.removeEventListener( 'mousemove', onMouseMove, false );
- scope.document.removeEventListener( 'mouseup', onMouseUp, false );
- }
- function onKeyDown( event ) {
- var currentMode = scope.mode;
- var currentSpace = scope.space;
- var currentScale = scope.scale;
- if ( event.keyCode == 87 ) { // W
- if ( scope.mode == 'translate' ) scope.space = ( scope.space == 'world' ) ? 'local' : 'world';
- scope.mode = 'translate';
- }
- if ( event.keyCode == 69 ) { // E
- if ( scope.mode == 'rotate' ) scope.space = ( scope.space == 'world' ) ? 'local' : 'world';
- scope.mode = 'rotate';
- }
- if ( event.keyCode == 82 ) { // R
- scope.mode = 'scale';
- scope.space = 'local';
- }
- if ( event.keyCode == 187 || event.keyCode == 107 ) { // +,=,num+
- scope.scale += 0.1
- }
- if ( event.keyCode == 189 || event.keyCode == 109) { // -,_,num-
- scope.scale -= 0.1
- scope.scale = Math.max( scope.scale, 0.1 );
- }
- if ( scope.mode !== currentMode || scope.space !== currentSpace || scope.scale !== currentScale ) {
- scope.setMode( scope.mode );
- scope.dispatchEvent( changeEvent );
- }
- }
- function intersectObjects( event, objects ) {
- pointerVector.set(
- ( event.layerX / scope.domElement.offsetWidth ) * 2 - 1,
- - ( event.layerY / scope.domElement.offsetHeight ) * 2 + 1,
- 0.5
- );
- projector.unprojectVector( pointerVector, scope.camera );
- ray.set( camPosition, pointerVector.sub( camPosition ).normalize() );
- var intersections = ray.intersectObjects( objects, true );
- return intersections[0] ? intersections[0] : false;
- }
- function isActive( name ) {
- if ( scope.active.search( name ) != -1 ) return true;
- else return false;
- }
- function bakeTransformations( object ) {
- var tempGeometry = new THREE.Geometry();
- THREE.GeometryUtils.merge( tempGeometry, object );
- object.setGeometry( tempGeometry );
- object.position.set( 0, 0, 0 );
- object.rotation.set( 0, 0, 0 );
- object.scale.set( 1, 1, 1 );
- }
- };
- THREE.TransformControls.prototype = Object.create( THREE.EventDispatcher.prototype );
|