| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170 |
- /**
- * @author arodic / https://github.com/arodic
- */
- (function () {
- 'use strict';
- var GizmoMaterial = function (parameters) {
- THREE.MeshBasicMaterial.call(this);
- this.depthTest = false;
- this.depthWrite = false;
- this.side = THREE.FrontSide;
- this.transparent = true;
- this.setValues(parameters);
- this.oldColor = this.color.clone();
- this.oldOpacity = this.opacity;
- this.highlight = function (highlighted) {
- if (highlighted) {
- this.color.setRGB(1, 1, 0);
- this.opacity = 1;
- } else {
- this.color.copy(this.oldColor);
- this.opacity = this.oldOpacity;
- }
- };
- };
- GizmoMaterial.prototype = Object.create(THREE.MeshBasicMaterial.prototype);
- GizmoMaterial.prototype.constructor = GizmoMaterial;
- var GizmoLineMaterial = function (parameters) {
- THREE.LineBasicMaterial.call(this);
- this.depthTest = false;
- this.depthWrite = false;
- this.transparent = true;
- this.linewidth = 1;
- this.setValues(parameters);
- this.oldColor = this.color.clone();
- this.oldOpacity = this.opacity;
- this.highlight = function (highlighted) {
- if (highlighted) {
- this.color.setRGB(1, 1, 0);
- this.opacity = 1;
- } else {
- this.color.copy(this.oldColor);
- this.opacity = this.oldOpacity;
- }
- };
- };
- GizmoLineMaterial.prototype = Object.create(THREE.LineBasicMaterial.prototype);
- GizmoLineMaterial.prototype.constructor = GizmoLineMaterial;
- var pickerMaterial = new GizmoMaterial({visible: false, transparent: false});
- THREE.TransformGizmo = function () {
- var scope = this;
- this.init = function () {
- THREE.Object3D.call(this);
- this.handles = new THREE.Object3D();
- this.pickers = new THREE.Object3D();
- this.planes = new THREE.Object3D();
- this.add(this.handles);
- this.add(this.pickers);
- this.add(this.planes);
- //// PLANES
- var planeGeometry = new THREE.PlaneBufferGeometry(50, 50, 2, 2);
- var planeMaterial = new THREE.MeshBasicMaterial({visible: false, side: THREE.DoubleSide});
- var planes = {
- "XY": new THREE.Mesh(planeGeometry, planeMaterial),
- "YZ": new THREE.Mesh(planeGeometry, planeMaterial),
- "XZ": new THREE.Mesh(planeGeometry, planeMaterial),
- "XYZE": new THREE.Mesh(planeGeometry, planeMaterial)
- };
- this.activePlane = planes[ "XYZE" ];
- planes[ "YZ" ].rotation.set(0, Math.PI / 2, 0);
- planes[ "XZ" ].rotation.set(-Math.PI / 2, 0, 0);
- for (var i in planes) {
- planes[ i ].name = i;
- this.planes.add(planes[ i ]);
- this.planes[ i ] = planes[ i ];
- }
- //// HANDLES AND PICKERS
- var setupGizmos = function (gizmoMap, parent) {
- for (var name in gizmoMap) {
- for (i = gizmoMap[ name ].length; i--; ) {
- var object = gizmoMap[ name ][ i ][ 0 ];
- var position = gizmoMap[ name ][ i ][ 1 ];
- var rotation = gizmoMap[ name ][ i ][ 2 ];
- object.name = name;
- if (position)
- object.position.set(position[ 0 ], position[ 1 ], position[ 2 ]);
- if (rotation)
- object.rotation.set(rotation[ 0 ], rotation[ 1 ], rotation[ 2 ]);
- parent.add(object);
- }
- }
- };
- setupGizmos(this.handleGizmos, this.handles);
- setupGizmos(this.pickerGizmos, this.pickers);
- // reset Transformations
- this.traverse(function (child) {
- if (child instanceof THREE.Mesh) {
- child.updateMatrix();
- var tempGeometry = child.geometry.clone();
- tempGeometry.applyMatrix(child.matrix);
- child.geometry = tempGeometry;
- child.position.set(0, 0, 0);
- child.rotation.set(0, 0, 0);
- child.scale.set(1, 1, 1);
- }
- });
- };
- this.highlight = function (axis) {
- this.traverse(function (child) {
- if (child.material && child.material.highlight) {
- if (child.name === axis) {
- child.material.highlight(true);
- } else {
- child.material.highlight(false);
- }
- }
- });
- };
- };
- THREE.TransformGizmo.prototype = Object.create(THREE.Object3D.prototype);
- THREE.TransformGizmo.prototype.constructor = THREE.TransformGizmo;
- THREE.TransformGizmo.prototype.update = function (rotation, eye) {
- var vec1 = new THREE.Vector3(0, 0, 0);
- var vec2 = new THREE.Vector3(0, 1, 0);
- var lookAtMatrix = new THREE.Matrix4();
- this.traverse(function (child) {
- if (child.name.search("E") !== -1) {
- child.quaternion.setFromRotationMatrix(lookAtMatrix.lookAt(eye, vec1, vec2));
- } else if (child.name.search("X") !== -1 || child.name.search("Y") !== -1 || child.name.search("Z") !== -1) {
- child.quaternion.setFromEuler(rotation);
- }
- });
- };
- THREE.TransformGizmoTranslate = function () {
- THREE.TransformGizmo.call(this);
- var arrowGeometry = new THREE.Geometry();
- var mesh = new THREE.Mesh(new THREE.CylinderGeometry(0, 0.05, 0.2, 12, 1, false));
- mesh.position.y = 0.5;
- mesh.updateMatrix();
- arrowGeometry.merge(mesh.geometry, mesh.matrix);
- var lineXGeometry = new THREE.BufferGeometry();
- lineXGeometry.addAttribute('position', new THREE.Float32Attribute([0, 0, 0, 1, 0, 0], 3));
- var lineYGeometry = new THREE.BufferGeometry();
- lineYGeometry.addAttribute('position', new THREE.Float32Attribute([0, 0, 0, 0, 1, 0], 3));
- var lineZGeometry = new THREE.BufferGeometry();
- lineZGeometry.addAttribute('position', new THREE.Float32Attribute([0, 0, 0, 0, 0, 1], 3));
- this.handleGizmos = {
- X: [
- [new THREE.Mesh(arrowGeometry, new GizmoMaterial({color: 0xff0000})), [0.5, 0, 0], [0, 0, -Math.PI / 2]],
- [new THREE.Line(lineXGeometry, new GizmoLineMaterial({color: 0xff0000}))]
- ],
- Y: [
- [new THREE.Mesh(arrowGeometry, new GizmoMaterial({color: 0x00ff00})), [0, 0.5, 0]],
- [new THREE.Line(lineYGeometry, new GizmoLineMaterial({color: 0x00ff00}))]
- ],
- Z: [
- [new THREE.Mesh(arrowGeometry, new GizmoMaterial({color: 0x0000ff})), [0, 0, 0.5], [Math.PI / 2, 0, 0]],
- [new THREE.Line(lineZGeometry, new GizmoLineMaterial({color: 0x0000ff}))]
- ],
- XYZ: [
- [new THREE.Mesh(new THREE.OctahedronGeometry(0.1, 0), new GizmoMaterial({color: 0xffffff, opacity: 0.25})), [0, 0, 0], [0, 0, 0]]
- ],
- XY: [
- [new THREE.Mesh(new THREE.PlaneBufferGeometry(0.29, 0.29), new GizmoMaterial({color: 0xffff00, opacity: 0.25})), [0.15, 0.15, 0]]
- ],
- YZ: [
- [new THREE.Mesh(new THREE.PlaneBufferGeometry(0.29, 0.29), new GizmoMaterial({color: 0x00ffff, opacity: 0.25})), [0, 0.15, 0.15], [0, Math.PI / 2, 0]]
- ],
- XZ: [
- [new THREE.Mesh(new THREE.PlaneBufferGeometry(0.29, 0.29), new GizmoMaterial({color: 0xff00ff, opacity: 0.25})), [0.15, 0, 0.15], [-Math.PI / 2, 0, 0]]
- ]
- };
- this.pickerGizmos = {
- X: [
- [new THREE.Mesh(new THREE.CylinderBufferGeometry(0.2, 0, 1, 4, 1, false), pickerMaterial), [0.6, 0, 0], [0, 0, -Math.PI / 2]]
- ],
- Y: [
- [new THREE.Mesh(new THREE.CylinderBufferGeometry(0.2, 0, 1, 4, 1, false), pickerMaterial), [0, 0.6, 0]]
- ],
- Z: [
- [new THREE.Mesh(new THREE.CylinderBufferGeometry(0.2, 0, 1, 4, 1, false), pickerMaterial), [0, 0, 0.6], [Math.PI / 2, 0, 0]]
- ],
- XYZ: [
- [new THREE.Mesh(new THREE.OctahedronGeometry(0.2, 0), pickerMaterial)]
- ],
- XY: [
- [new THREE.Mesh(new THREE.PlaneBufferGeometry(0.4, 0.4), pickerMaterial), [0.2, 0.2, 0]]
- ],
- YZ: [
- [new THREE.Mesh(new THREE.PlaneBufferGeometry(0.4, 0.4), pickerMaterial), [0, 0.2, 0.2], [0, Math.PI / 2, 0]]
- ],
- XZ: [
- [new THREE.Mesh(new THREE.PlaneBufferGeometry(0.4, 0.4), pickerMaterial), [0.2, 0, 0.2], [-Math.PI / 2, 0, 0]]
- ]
- };
- this.setActivePlane = function (axis, eye) {
- var tempMatrix = new THREE.Matrix4();
- eye.applyMatrix4(tempMatrix.getInverse(tempMatrix.extractRotation(this.planes[ "XY" ].matrixWorld)));
- if (axis === "X") {
- this.activePlane = this.planes[ "XY" ];
- if (Math.abs(eye.y) > Math.abs(eye.z))
- this.activePlane = this.planes[ "XZ" ];
- }
- if (axis === "Y") {
- this.activePlane = this.planes[ "XY" ];
- if (Math.abs(eye.x) > Math.abs(eye.z))
- this.activePlane = this.planes[ "YZ" ];
- }
- if (axis === "Z") {
- this.activePlane = this.planes[ "XZ" ];
- if (Math.abs(eye.x) > Math.abs(eye.y))
- this.activePlane = this.planes[ "YZ" ];
- }
- if (axis === "XYZ")
- this.activePlane = this.planes[ "XYZE" ];
- if (axis === "XY")
- this.activePlane = this.planes[ "XY" ];
- if (axis === "YZ")
- this.activePlane = this.planes[ "YZ" ];
- if (axis === "XZ")
- this.activePlane = this.planes[ "XZ" ];
- };
- this.init();
- };
- THREE.TransformGizmoTranslate.prototype = Object.create(THREE.TransformGizmo.prototype);
- THREE.TransformGizmoTranslate.prototype.constructor = THREE.TransformGizmoTranslate;
- THREE.TransformGizmoRotate = function () {
- THREE.TransformGizmo.call(this);
- var CircleGeometry = function (radius, facing, arc) {
- var geometry = new THREE.BufferGeometry();
- var vertices = [];
- arc = arc ? arc : 1;
- for (var i = 0; i <= 64 * arc; ++i) {
- if (facing === 'x')
- vertices.push(0, Math.cos(i / 32 * Math.PI) * radius, Math.sin(i / 32 * Math.PI) * radius);
- if (facing === 'y')
- vertices.push(Math.cos(i / 32 * Math.PI) * radius, 0, Math.sin(i / 32 * Math.PI) * radius);
- if (facing === 'z')
- vertices.push(Math.sin(i / 32 * Math.PI) * radius, Math.cos(i / 32 * Math.PI) * radius, 0);
- }
- geometry.addAttribute('position', new THREE.Float32Attribute(vertices, 3));
- return geometry;
- };
- this.handleGizmos = {
- X: [
- [new THREE.Line(new CircleGeometry(1, 'x', 0.5), new GizmoLineMaterial({color: 0xff0000}))]
- ],
- Y: [
- [new THREE.Line(new CircleGeometry(1, 'y', 0.5), new GizmoLineMaterial({color: 0x00ff00}))]
- ],
- Z: [
- [new THREE.Line(new CircleGeometry(1, 'z', 0.5), new GizmoLineMaterial({color: 0x0000ff}))]
- ],
- E: [
- [new THREE.Line(new CircleGeometry(1.25, 'z', 1), new GizmoLineMaterial({color: 0xcccc00}))]
- ],
- XYZE: [
- [new THREE.Line(new CircleGeometry(1, 'z', 1), new GizmoLineMaterial({color: 0x787878}))]
- ]
- };
- this.pickerGizmos = {
- X: [
- [new THREE.Mesh(new THREE.TorusBufferGeometry(1, 0.12, 4, 12, Math.PI), pickerMaterial), [0, 0, 0], [0, -Math.PI / 2, -Math.PI / 2]]
- ],
- Y: [
- [new THREE.Mesh(new THREE.TorusBufferGeometry(1, 0.12, 4, 12, Math.PI), pickerMaterial), [0, 0, 0], [Math.PI / 2, 0, 0]]
- ],
- Z: [
- [new THREE.Mesh(new THREE.TorusBufferGeometry(1, 0.12, 4, 12, Math.PI), pickerMaterial), [0, 0, 0], [0, 0, -Math.PI / 2]]
- ],
- E: [
- [new THREE.Mesh(new THREE.TorusBufferGeometry(1.25, 0.12, 2, 24), pickerMaterial)]
- ],
- XYZE: [
- [new THREE.Mesh(new THREE.Geometry())]// TODO
- ]
- };
- this.setActivePlane = function (axis) {
- if (axis === "E")
- this.activePlane = this.planes[ "XYZE" ];
- if (axis === "X")
- this.activePlane = this.planes[ "YZ" ];
- if (axis === "Y")
- this.activePlane = this.planes[ "XZ" ];
- if (axis === "Z")
- this.activePlane = this.planes[ "XY" ];
- };
- this.update = function (rotation, eye2) {
- THREE.TransformGizmo.prototype.update.apply(this, arguments);
- var group = {
- handles: this[ "handles" ],
- pickers: this[ "pickers" ],
- };
- var tempMatrix = new THREE.Matrix4();
- var worldRotation = new THREE.Euler(0, 0, 1);
- 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 quaternionX = new THREE.Quaternion();
- var quaternionY = new THREE.Quaternion();
- var quaternionZ = new THREE.Quaternion();
- var eye = eye2.clone();
- worldRotation.copy(this.planes[ "XY" ].rotation);
- tempQuaternion.setFromEuler(worldRotation);
- tempMatrix.makeRotationFromQuaternion(tempQuaternion).getInverse(tempMatrix);
- eye.applyMatrix4(tempMatrix);
- this.traverse(function (child) {
- tempQuaternion.setFromEuler(worldRotation);
- if (child.name === "X") {
- quaternionX.setFromAxisAngle(unitX, Math.atan2(-eye.y, eye.z));
- tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionX);
- child.quaternion.copy(tempQuaternion);
- }
- if (child.name === "Y") {
- quaternionY.setFromAxisAngle(unitY, Math.atan2(eye.x, eye.z));
- tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionY);
- child.quaternion.copy(tempQuaternion);
- }
- if (child.name === "Z") {
- quaternionZ.setFromAxisAngle(unitZ, Math.atan2(eye.y, eye.x));
- tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionZ);
- child.quaternion.copy(tempQuaternion);
- }
- });
- };
- this.init();
- };
- THREE.TransformGizmoRotate.prototype = Object.create(THREE.TransformGizmo.prototype);
- THREE.TransformGizmoRotate.prototype.constructor = THREE.TransformGizmoRotate;
- THREE.TransformGizmoScale = function () {
- THREE.TransformGizmo.call(this);
- var arrowGeometry = new THREE.Geometry();
- var mesh = new THREE.Mesh(new THREE.BoxGeometry(0.125, 0.125, 0.125));
- mesh.position.y = 0.5;
- mesh.updateMatrix();
- arrowGeometry.merge(mesh.geometry, mesh.matrix);
- var lineXGeometry = new THREE.BufferGeometry();
- lineXGeometry.addAttribute('position', new THREE.Float32Attribute([0, 0, 0, 1, 0, 0], 3));
- var lineYGeometry = new THREE.BufferGeometry();
- lineYGeometry.addAttribute('position', new THREE.Float32Attribute([0, 0, 0, 0, 1, 0], 3));
- var lineZGeometry = new THREE.BufferGeometry();
- lineZGeometry.addAttribute('position', new THREE.Float32Attribute([0, 0, 0, 0, 0, 1], 3));
- this.handleGizmos = {
- X: [
- [new THREE.Mesh(arrowGeometry, new GizmoMaterial({color: 0xff0000})), [0.5, 0, 0], [0, 0, -Math.PI / 2]],
- [new THREE.Line(lineXGeometry, new GizmoLineMaterial({color: 0xff0000}))]
- ],
- Y: [
- [new THREE.Mesh(arrowGeometry, new GizmoMaterial({color: 0x00ff00})), [0, 0.5, 0]],
- [new THREE.Line(lineYGeometry, new GizmoLineMaterial({color: 0x00ff00}))]
- ],
- Z: [
- [new THREE.Mesh(arrowGeometry, new GizmoMaterial({color: 0x0000ff})), [0, 0, 0.5], [Math.PI / 2, 0, 0]],
- [new THREE.Line(lineZGeometry, new GizmoLineMaterial({color: 0x0000ff}))]
- ],
- XYZ: [
- [new THREE.Mesh(new THREE.BoxBufferGeometry(0.125, 0.125, 0.125), new GizmoMaterial({color: 0xffffff, opacity: 0.25}))]
- ]
- };
- this.pickerGizmos = {
- X: [
- [new THREE.Mesh(new THREE.CylinderBufferGeometry(0.2, 0, 1, 4, 1, false), pickerMaterial), [0.6, 0, 0], [0, 0, -Math.PI / 2]]
- ],
- Y: [
- [new THREE.Mesh(new THREE.CylinderBufferGeometry(0.2, 0, 1, 4, 1, false), pickerMaterial), [0, 0.6, 0]]
- ],
- Z: [
- [new THREE.Mesh(new THREE.CylinderBufferGeometry(0.2, 0, 1, 4, 1, false), pickerMaterial), [0, 0, 0.6], [Math.PI / 2, 0, 0]]
- ],
- XYZ: [
- [new THREE.Mesh(new THREE.BoxBufferGeometry(0.4, 0.4, 0.4), pickerMaterial)]
- ]
- };
- this.setActivePlane = function (axis, eye) {
- var tempMatrix = new THREE.Matrix4();
- eye.applyMatrix4(tempMatrix.getInverse(tempMatrix.extractRotation(this.planes[ "XY" ].matrixWorld)));
- if (axis === "X") {
- this.activePlane = this.planes[ "XY" ];
- if (Math.abs(eye.y) > Math.abs(eye.z))
- this.activePlane = this.planes[ "XZ" ];
- }
- if (axis === "Y") {
- this.activePlane = this.planes[ "XY" ];
- if (Math.abs(eye.x) > Math.abs(eye.z))
- this.activePlane = this.planes[ "YZ" ];
- }
- if (axis === "Z") {
- this.activePlane = this.planes[ "XZ" ];
- if (Math.abs(eye.x) > Math.abs(eye.y))
- this.activePlane = this.planes[ "YZ" ];
- }
- if (axis === "XYZ")
- this.activePlane = this.planes[ "XYZE" ];
- };
- this.init();
- };
- THREE.TransformGizmoScale.prototype = Object.create(THREE.TransformGizmo.prototype);
- THREE.TransformGizmoScale.prototype.constructor = THREE.TransformGizmoScale;
- THREE.TransformControls = function (camera, domElement) {
- // TODO: Make non-uniform scale and rotate play nice in hierarchies
- // TODO: ADD RXYZ contol
- THREE.Object3D.call(this);
- domElement = (domElement !== undefined) ? domElement : document;
- this.body = undefined;
- this.object = undefined;
- this.visible = false;
- this.translationSnap = null;
- this.rotationSnap = null;
- this.space = "world";
- this.size = 1;
- this.axis = null;
- var scope = this;
- var _mode = "translate";
- var _dragging = false;
- var _plane = "XY";
- var _gizmo = {
- "translate": new THREE.TransformGizmoTranslate(),
- "rotate": new THREE.TransformGizmoRotate(),
- "scale": new THREE.TransformGizmoScale()
- };
- for (var type in _gizmo) {
- var gizmoObj = _gizmo[ type ];
- gizmoObj.visible = (type === _mode);
- this.add(gizmoObj);
- }
- var changeEvent = {type: "change"};
- var mouseDownEvent = {type: "mouseDown"};
- var mouseUpEvent = {type: "mouseUp", mode: _mode};
- var objectChangeEvent = {type: "objectChange"};
- var ray = new THREE.Raycaster();
- var pointerVector = new THREE.Vector2();
- 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.Euler();
- var worldRotationMatrix = new THREE.Matrix4();
- var camPosition = new THREE.Vector3();
- var camRotation = new THREE.Euler();
- domElement.addEventListener("mousedown", onPointerDown, false);
- domElement.addEventListener("touchstart", onPointerDown, false);
- domElement.addEventListener("mousemove", onPointerHover, false);
- domElement.addEventListener("touchmove", onPointerHover, false);
- domElement.addEventListener("mousemove", onPointerMove, false);
- domElement.addEventListener("touchmove", onPointerMove, false);
- domElement.addEventListener("mouseup", onPointerUp, false);
- domElement.addEventListener("mouseout", onPointerUp, false);
- domElement.addEventListener("touchend", onPointerUp, false);
- domElement.addEventListener("touchcancel", onPointerUp, false);
- domElement.addEventListener("touchleave", onPointerUp, false);
- this.dispose = function () {
- domElement.removeEventListener("mousedown", onPointerDown);
- domElement.removeEventListener("touchstart", onPointerDown);
- domElement.removeEventListener("mousemove", onPointerHover);
- domElement.removeEventListener("touchmove", onPointerHover);
- domElement.removeEventListener("mousemove", onPointerMove);
- domElement.removeEventListener("touchmove", onPointerMove);
- domElement.removeEventListener("mouseup", onPointerUp);
- domElement.removeEventListener("mouseout", onPointerUp);
- domElement.removeEventListener("touchend", onPointerUp);
- domElement.removeEventListener("touchcancel", onPointerUp);
- domElement.removeEventListener("touchleave", onPointerUp);
- };
- this.attach = function (object, body) {
- this.body = body;
- this.object = object;
- this.visible = true;
- this.update();
- };
- this.detach = function () {
- this.body = undefined;
- this.object = undefined;
- this.visible = false;
- this.axis = null;
- };
- this.getMode = function () {
- return _mode;
- };
- this.setMode = function (mode) {
- _mode = mode ? mode : _mode;
- if (_mode === "scale")
- scope.space = "local";
- for (var type in _gizmo)
- _gizmo[ type ].visible = (type === _mode);
- this.update();
- scope.dispatchEvent(changeEvent);
- };
- this.setTranslationSnap = function (translationSnap) {
- scope.translationSnap = translationSnap;
- };
- this.setRotationSnap = function (rotationSnap) {
- scope.rotationSnap = rotationSnap;
- };
- this.setSize = function (size) {
- scope.size = size;
- this.update();
- scope.dispatchEvent(changeEvent);
- };
- this.setSpace = function (space) {
- scope.space = space;
- this.update();
- scope.dispatchEvent(changeEvent);
- };
- this.update = function () {
- if (scope.object === undefined)
- return;
- scope.object.updateMatrixWorld();
- worldPosition.setFromMatrixPosition(scope.object.matrixWorld);
- worldRotation.setFromRotationMatrix(tempMatrix.extractRotation(scope.object.matrixWorld));
- camera.updateMatrixWorld();
- camPosition.setFromMatrixPosition(camera.matrixWorld);
- camRotation.setFromRotationMatrix(tempMatrix.extractRotation(camera.matrixWorld));
- scale = worldPosition.distanceTo(camPosition) / 6 * scope.size;
- this.position.copy(worldPosition);
- this.scale.set(scale, scale, scale);
- eye.copy(camPosition).sub(worldPosition).normalize();
- if (scope.space === "local") {
- _gizmo[ _mode ].update(worldRotation, eye);
- } else if (scope.space === "world") {
- _gizmo[ _mode ].update(new THREE.Euler(), eye);
- }
- _gizmo[ _mode ].highlight(scope.axis);
- };
- function onPointerHover(event) {
- if (scope.object === undefined || _dragging === true || (event.button !== undefined && event.button !== 0))
- return;
- var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
- var intersect = intersectObjects(pointer, _gizmo[ _mode ].pickers.children);
- var axis = null;
- if (intersect) {
- axis = intersect.object.name;
- event.preventDefault();
- }
- if (scope.axis !== axis) {
- scope.axis = axis;
- scope.update();
- scope.dispatchEvent(changeEvent);
- }
- }
- function onPointerDown(event) {
- if (scope.object === undefined || _dragging === true || (event.button !== undefined && event.button !== 0))
- return;
- var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
- if (pointer.button === 0 || pointer.button === undefined) {
- var intersect = intersectObjects(pointer, _gizmo[ _mode ].pickers.children);
- if (intersect) {
- event.preventDefault();
- event.stopPropagation();
- scope.dispatchEvent(mouseDownEvent);
- scope.axis = intersect.object.name;
- scope.update();
- eye.copy(camPosition).sub(worldPosition).normalize();
- _gizmo[ _mode ].setActivePlane(scope.axis, eye);
- var planeIntersect = intersectObjects(pointer, [_gizmo[ _mode ].activePlane]);
- 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.setFromMatrixScale(tempMatrix.getInverse(scope.object.parent.matrixWorld));
- offset.copy(planeIntersect.point);
- }
- }
- }
- _dragging = true;
- }
- function onPointerMove(event) {
- if (scope.object === undefined || scope.axis === null || _dragging === false || (event.button !== undefined && event.button !== 0))
- return;
- var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
- var planeIntersect = intersectObjects(pointer, [_gizmo[ _mode ].activePlane]);
- if (planeIntersect === false)
- return;
- event.preventDefault();
- event.stopPropagation();
- point.copy(planeIntersect.point);
- if (_mode === "translate") {
- point.sub(offset);
- point.multiply(parentScale);
- if (scope.space === "local") {
- point.applyMatrix4(tempMatrix.getInverse(worldRotationMatrix));
- if (scope.axis.search("X") === -1)
- point.x = 0;
- if (scope.axis.search("Y") === -1)
- point.y = 0;
- if (scope.axis.search("Z") === -1)
- point.z = 0;
- point.applyMatrix4(oldRotationMatrix);
- scope.object.position.copy(oldPosition);
- scope.object.position.add(point);
- scope.body.position.copy(scope.object.position);
- }
- if (scope.space === "world" || scope.axis.search("XYZ") !== -1) {
- if (scope.axis.search("X") === -1)
- point.x = 0;
- if (scope.axis.search("Y") === -1)
- point.y = 0;
- if (scope.axis.search("Z") === -1)
- point.z = 0;
- point.applyMatrix4(tempMatrix.getInverse(parentRotationMatrix));
- scope.object.position.copy(oldPosition);
- scope.object.position.add(point);
- scope.body.position.copy(scope.object.position);
- }
- if (scope.translationSnap !== null) {
- if (scope.space === "local") {
- scope.object.position.applyMatrix4(tempMatrix.getInverse(worldRotationMatrix));
- }
- if (scope.axis.search("X") !== -1)
- scope.object.position.x = Math.round(scope.object.position.x / scope.translationSnap) * scope.translationSnap;
- if (scope.axis.search("Y") !== -1)
- scope.object.position.y = Math.round(scope.object.position.y / scope.translationSnap) * scope.translationSnap;
- if (scope.axis.search("Z") !== -1)
- scope.object.position.z = Math.round(scope.object.position.z / scope.translationSnap) * scope.translationSnap;
- if (scope.space === "local") {
- scope.object.position.applyMatrix4(worldRotationMatrix);
- }
- }
- } else if (_mode === "scale") {
- point.sub(offset);
- point.multiply(parentScale);
- if (scope.space === "local") {
- if (scope.axis === "XYZ") {
- scale = 1 + ((point.y) / Math.max(oldScale.x, oldScale.y, oldScale.z));
- 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 (scope.axis === "X")
- scope.object.scale.x = oldScale.x * (1 + point.x / oldScale.x);
- if (scope.axis === "Y")
- scope.object.scale.y = oldScale.y * (1 + point.y / oldScale.y);
- if (scope.axis === "Z")
- scope.object.scale.z = oldScale.z * (1 + point.z / oldScale.z);
- }
- }
- } else if (_mode === "rotate") {
- point.sub(worldPosition);
- point.multiply(parentScale);
- tempVector.copy(offset).sub(worldPosition);
- tempVector.multiply(parentScale);
- if (scope.axis === "E") {
- 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.quaternion.copy(tempQuaternion);
- scope.body.quaternion.copy(tempQuaternion);
- } else if (scope.axis === "XYZE") {
- 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.quaternion.copy(tempQuaternion);
- scope.body.quaternion.copy(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);
- if (scope.rotationSnap !== null) {
- quaternionX.setFromAxisAngle(unitX, Math.round((rotation.x - offsetRotation.x) / scope.rotationSnap) * scope.rotationSnap);
- quaternionY.setFromAxisAngle(unitY, Math.round((rotation.y - offsetRotation.y) / scope.rotationSnap) * scope.rotationSnap);
- quaternionZ.setFromAxisAngle(unitZ, Math.round((rotation.z - offsetRotation.z) / scope.rotationSnap) * scope.rotationSnap);
- } else {
- quaternionX.setFromAxisAngle(unitX, rotation.x - offsetRotation.x);
- quaternionY.setFromAxisAngle(unitY, rotation.y - offsetRotation.y);
- quaternionZ.setFromAxisAngle(unitZ, rotation.z - offsetRotation.z);
- }
- if (scope.axis === "X")
- quaternionXYZ.multiplyQuaternions(quaternionXYZ, quaternionX);
- if (scope.axis === "Y")
- quaternionXYZ.multiplyQuaternions(quaternionXYZ, quaternionY);
- if (scope.axis === "Z")
- quaternionXYZ.multiplyQuaternions(quaternionXYZ, quaternionZ);
- scope.object.quaternion.copy(quaternionXYZ);
- scope.body.quaternion.copy(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));
- if (scope.rotationSnap !== null) {
- quaternionX.setFromAxisAngle(unitX, Math.round((rotation.x - offsetRotation.x) / scope.rotationSnap) * scope.rotationSnap);
- quaternionY.setFromAxisAngle(unitY, Math.round((rotation.y - offsetRotation.y) / scope.rotationSnap) * scope.rotationSnap);
- quaternionZ.setFromAxisAngle(unitZ, Math.round((rotation.z - offsetRotation.z) / scope.rotationSnap) * scope.rotationSnap);
- } else {
- 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.axis === "X")
- tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionX);
- if (scope.axis === "Y")
- tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionY);
- if (scope.axis === "Z")
- tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionZ);
- tempQuaternion.multiplyQuaternions(tempQuaternion, quaternionXYZ);
- scope.object.quaternion.copy(tempQuaternion);
- scope.body.quaternion.copy(tempQuaternion);
- }
- }
- scope.update();
- scope.dispatchEvent(changeEvent);
- scope.dispatchEvent(objectChangeEvent);
- }
- function onPointerUp(event) {
- event.preventDefault(); // Prevent MouseEvent on mobile
- if (event.button !== undefined && event.button !== 0)
- return;
- if (_dragging && (scope.axis !== null)) {
- mouseUpEvent.mode = _mode;
- scope.dispatchEvent(mouseUpEvent);
- }
- _dragging = false;
- if (event instanceof TouchEvent) {
- // Force "rollover"
- scope.axis = null;
- scope.update();
- scope.dispatchEvent(changeEvent);
- } else {
- onPointerHover(event);
- }
- }
- function intersectObjects(pointer, objects) {
- var rect = domElement.getBoundingClientRect();
- var x = (pointer.clientX - rect.left) / rect.width;
- var y = (pointer.clientY - rect.top) / rect.height;
- pointerVector.set((x * 2) - 1, -(y * 2) + 1);
- ray.setFromCamera(pointerVector, camera);
- var intersections = ray.intersectObjects(objects, true);
- return intersections[ 0 ] ? intersections[ 0 ] : false;
- }
- };
- THREE.TransformControls.prototype = Object.create(THREE.Object3D.prototype);
- THREE.TransformControls.prototype.constructor = THREE.TransformControls;
- }());
|