@sauskylark/potree
Version:
WebGL point cloud viewer
872 lines (706 loc) • 27.8 kB
JavaScript
import * as THREE from "../../libs/three.js/build/three.module.js";
import {Utils} from "../utils.js";
export class TransformationTool {
constructor(viewer) {
this.viewer = viewer;
this.scene = new THREE.Scene();
this.selection = [];
this.pivot = new THREE.Vector3();
this.dragging = false;
this.showPickVolumes = false;
this.viewer.inputHandler.registerInteractiveScene(this.scene);
this.viewer.inputHandler.addEventListener('selection_changed', (e) => {
for(let selected of this.selection){
this.viewer.inputHandler.blacklist.delete(selected);
}
this.selection = e.selection;
for(let selected of this.selection){
this.viewer.inputHandler.blacklist.add(selected);
}
});
let red = 0xE73100;
let green = 0x44A24A;
let blue = 0x2669E7;
this.activeHandle = null;
this.scaleHandles = {
"scale.x+": {name: "scale.x+", node: new THREE.Object3D(), color: red, alignment: [+1, +0, +0]},
"scale.x-": {name: "scale.x-", node: new THREE.Object3D(), color: red, alignment: [-1, +0, +0]},
"scale.y+": {name: "scale.y+", node: new THREE.Object3D(), color: green, alignment: [+0, +1, +0]},
"scale.y-": {name: "scale.y-", node: new THREE.Object3D(), color: green, alignment: [+0, -1, +0]},
"scale.z+": {name: "scale.z+", node: new THREE.Object3D(), color: blue, alignment: [+0, +0, +1]},
"scale.z-": {name: "scale.z-", node: new THREE.Object3D(), color: blue, alignment: [+0, +0, -1]},
};
this.focusHandles = {
"focus.x+": {name: "focus.x+", node: new THREE.Object3D(), color: red, alignment: [+1, +0, +0]},
"focus.x-": {name: "focus.x-", node: new THREE.Object3D(), color: red, alignment: [-1, +0, +0]},
"focus.y+": {name: "focus.y+", node: new THREE.Object3D(), color: green, alignment: [+0, +1, +0]},
"focus.y-": {name: "focus.y-", node: new THREE.Object3D(), color: green, alignment: [+0, -1, +0]},
"focus.z+": {name: "focus.z+", node: new THREE.Object3D(), color: blue, alignment: [+0, +0, +1]},
"focus.z-": {name: "focus.z-", node: new THREE.Object3D(), color: blue, alignment: [+0, +0, -1]},
};
this.translationHandles = {
"translation.x": {name: "translation.x", node: new THREE.Object3D(), color: red, alignment: [1, 0, 0]},
"translation.y": {name: "translation.y", node: new THREE.Object3D(), color: green, alignment: [0, 1, 0]},
"translation.z": {name: "translation.z", node: new THREE.Object3D(), color: blue, alignment: [0, 0, 1]},
};
this.rotationHandles = {
"rotation.x": {name: "rotation.x", node: new THREE.Object3D(), color: red, alignment: [1, 0, 0]},
"rotation.y": {name: "rotation.y", node: new THREE.Object3D(), color: green, alignment: [0, 1, 0]},
"rotation.z": {name: "rotation.z", node: new THREE.Object3D(), color: blue, alignment: [0, 0, 1]},
};
this.handles = Object.assign({}, this.scaleHandles, this.focusHandles, this.translationHandles, this.rotationHandles);
this.pickVolumes = [];
this.initializeScaleHandles();
this.initializeFocusHandles();
this.initializeTranslationHandles();
this.initializeRotationHandles();
let boxFrameGeometry = new THREE.Geometry();
{
// bottom
boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, 0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, 0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, 0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, -0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, -0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, -0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, -0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, 0.5));
// top
boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, 0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, 0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, 0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, -0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, -0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, -0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, -0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, 0.5));
// sides
boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, 0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, 0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, 0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, 0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, -0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, -0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, -0.5));
boxFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, -0.5));
}
this.frame = new THREE.LineSegments(boxFrameGeometry, new THREE.LineBasicMaterial({color: 0xffff00}));
this.scene.add(this.frame);
}
initializeScaleHandles(){
let sgSphere = new THREE.SphereGeometry(1, 32, 32);
let sgLowPolySphere = new THREE.SphereGeometry(1, 16, 16);
for(let handleName of Object.keys(this.scaleHandles)){
let handle = this.scaleHandles[handleName];
let node = handle.node;
this.scene.add(node);
node.position.set(...handle.alignment).multiplyScalar(0.5);
let material = new THREE.MeshBasicMaterial({
color: handle.color,
opacity: 0.4,
transparent: true
});
let outlineMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
side: THREE.BackSide,
opacity: 0.4,
transparent: true});
let pickMaterial = new THREE.MeshNormalMaterial({
opacity: 0.2,
transparent: true,
visible: this.showPickVolumes});
let sphere = new THREE.Mesh(sgSphere, material);
sphere.scale.set(1.3, 1.3, 1.3);
sphere.name = `${handleName}.handle`;
node.add(sphere);
let outline = new THREE.Mesh(sgSphere, outlineMaterial);
outline.scale.set(1.4, 1.4, 1.4);
outline.name = `${handleName}.outline`;
sphere.add(outline);
let pickSphere = new THREE.Mesh(sgLowPolySphere, pickMaterial);
pickSphere.name = `${handleName}.pick_volume`;
pickSphere.scale.set(3, 3, 3);
sphere.add(pickSphere);
pickSphere.handle = handleName;
this.pickVolumes.push(pickSphere);
node.setOpacity = (target) => {
let opacity = {x: material.opacity};
let t = new TWEEN.Tween(opacity).to({x: target}, 100);
t.onUpdate(() => {
sphere.visible = opacity.x > 0;
pickSphere.visible = opacity.x > 0;
material.opacity = opacity.x;
outlineMaterial.opacity = opacity.x;
pickSphere.material.opacity = opacity.x * 0.5;
});
t.start();
};
pickSphere.addEventListener("drag", (e) => this.dragScaleHandle(e));
pickSphere.addEventListener("drop", (e) => this.dropScaleHandle(e));
pickSphere.addEventListener("mouseover", e => {
//node.setOpacity(1);
});
pickSphere.addEventListener("click", e => {
e.consume();
});
pickSphere.addEventListener("mouseleave", e => {
//node.setOpacity(0.4);
});
}
}
initializeFocusHandles(){
//let sgBox = new THREE.BoxGeometry(1, 1, 1);
let sgPlane = new THREE.PlaneGeometry(4, 4, 1, 1);
let sgLowPolySphere = new THREE.SphereGeometry(1, 16, 16);
let texture = new THREE.TextureLoader().load(`${exports.resourcePath}/icons/eye_2.png`);
for(let handleName of Object.keys(this.focusHandles)){
let handle = this.focusHandles[handleName];
let node = handle.node;
this.scene.add(node);
let align = handle.alignment;
//node.lookAt(new THREE.Vector3().addVectors(node.position, new THREE.Vector3(...align)));
node.lookAt(new THREE.Vector3(...align));
let off = 0.8;
if(align[0] === 1){
node.position.set(1, off, -off).multiplyScalar(0.5);
node.rotation.z = Math.PI / 2;
}else if(align[0] === -1){
node.position.set(-1, -off, -off).multiplyScalar(0.5);
node.rotation.z = Math.PI / 2;
}else if(align[1] === 1){
node.position.set(-off, 1, -off).multiplyScalar(0.5);
node.rotation.set(Math.PI / 2, Math.PI, 0.0);
}else if(align[1] === -1){
node.position.set(off, -1, -off).multiplyScalar(0.5);
node.rotation.set(Math.PI / 2, 0.0, 0.0);
}else if(align[2] === 1){
node.position.set(off, off, 1).multiplyScalar(0.5);
}else if(align[2] === -1){
node.position.set(-off, off, -1).multiplyScalar(0.5);
}
let material = new THREE.MeshBasicMaterial({
color: handle.color,
opacity: 0,
transparent: true,
map: texture
});
//let outlineMaterial = new THREE.MeshBasicMaterial({
// color: 0x000000,
// side: THREE.BackSide,
// opacity: 0,
// transparent: true});
let pickMaterial = new THREE.MeshNormalMaterial({
//opacity: 0,
transparent: true,
visible: this.showPickVolumes});
let box = new THREE.Mesh(sgPlane, material);
box.name = `${handleName}.handle`;
box.scale.set(1.5, 1.5, 1.5);
box.position.set(0, 0, 0);
box.visible = false;
node.add(box);
//handle.focusNode = box;
//let outline = new THREE.Mesh(sgPlane, outlineMaterial);
//outline.scale.set(1.4, 1.4, 1.4);
//outline.name = `${handleName}.outline`;
//box.add(outline);
let pickSphere = new THREE.Mesh(sgLowPolySphere, pickMaterial);
pickSphere.name = `${handleName}.pick_volume`;
pickSphere.scale.set(3, 3, 3);
box.add(pickSphere);
pickSphere.handle = handleName;
this.pickVolumes.push(pickSphere);
node.setOpacity = (target) => {
let opacity = {x: material.opacity};
let t = new TWEEN.Tween(opacity).to({x: target}, 100);
t.onUpdate(() => {
pickSphere.visible = opacity.x > 0;
box.visible = opacity.x > 0;
material.opacity = opacity.x;
//outlineMaterial.opacity = opacity.x;
pickSphere.material.opacity = opacity.x * 0.5;
});
t.start();
};
pickSphere.addEventListener("drag", e => {});
pickSphere.addEventListener("mouseup", e => {
e.consume();
});
pickSphere.addEventListener("mousedown", e => {
e.consume();
});
pickSphere.addEventListener("click", e => {
e.consume();
let selected = this.selection[0];
let maxScale = Math.max(...selected.scale.toArray());
let minScale = Math.min(...selected.scale.toArray());
let handleLength = Math.abs(selected.scale.dot(new THREE.Vector3(...handle.alignment)));
let alignment = new THREE.Vector3(...handle.alignment).multiplyScalar(2 * maxScale / handleLength);
alignment.applyMatrix4(selected.matrixWorld);
let newCamPos = alignment;
let newCamTarget = selected.getWorldPosition(new THREE.Vector3());
Utils.moveTo(this.viewer.scene, newCamPos, newCamTarget);
});
pickSphere.addEventListener("mouseover", e => {
//box.setOpacity(1);
});
pickSphere.addEventListener("mouseleave", e => {
//box.setOpacity(0.4);
});
}
}
initializeTranslationHandles(){
let boxGeometry = new THREE.BoxGeometry(1, 1, 1);
for(let handleName of Object.keys(this.translationHandles)){
let handle = this.handles[handleName];
let node = handle.node;
this.scene.add(node);
let material = new THREE.MeshBasicMaterial({
color: handle.color,
opacity: 0.4,
transparent: true});
let outlineMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
side: THREE.BackSide,
opacity: 0.4,
transparent: true});
let pickMaterial = new THREE.MeshNormalMaterial({
opacity: 0.2,
transparent: true,
visible: this.showPickVolumes
});
let box = new THREE.Mesh(boxGeometry, material);
box.name = `${handleName}.handle`;
box.scale.set(0.2, 0.2, 40);
box.lookAt(new THREE.Vector3(...handle.alignment));
box.renderOrder = 10;
node.add(box);
handle.translateNode = box;
let outline = new THREE.Mesh(boxGeometry, outlineMaterial);
outline.name = `${handleName}.outline`;
outline.scale.set(3, 3, 1.03);
outline.renderOrder = 0;
box.add(outline);
let pickVolume = new THREE.Mesh(boxGeometry, pickMaterial);
pickVolume.name = `${handleName}.pick_volume`;
pickVolume.scale.set(12, 12, 1.1);
pickVolume.handle = handleName;
box.add(pickVolume);
this.pickVolumes.push(pickVolume);
node.setOpacity = (target) => {
let opacity = {x: material.opacity};
let t = new TWEEN.Tween(opacity).to({x: target}, 100);
t.onUpdate(() => {
box.visible = opacity.x > 0;
pickVolume.visible = opacity.x > 0;
material.opacity = opacity.x;
outlineMaterial.opacity = opacity.x;
pickMaterial.opacity = opacity.x * 0.5;
});
t.start();
};
pickVolume.addEventListener("drag", (e) => {this.dragTranslationHandle(e)});
pickVolume.addEventListener("drop", (e) => {this.dropTranslationHandle(e)});
}
}
initializeRotationHandles(){
let adjust = 0.5;
let torusGeometry = new THREE.TorusGeometry(1, adjust * 0.015, 8, 64, Math.PI / 2);
let outlineGeometry = new THREE.TorusGeometry(1, adjust * 0.04, 8, 64, Math.PI / 2);
let pickGeometry = new THREE.TorusGeometry(1, adjust * 0.1, 6, 4, Math.PI / 2);
for(let handleName of Object.keys(this.rotationHandles)){
let handle = this.handles[handleName];
let node = handle.node;
this.scene.add(node);
let material = new THREE.MeshBasicMaterial({
color: handle.color,
opacity: 0.4,
transparent: true});
let outlineMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
side: THREE.BackSide,
opacity: 0.4,
transparent: true});
let pickMaterial = new THREE.MeshNormalMaterial({
opacity: 0.2,
transparent: true,
visible: this.showPickVolumes
});
let box = new THREE.Mesh(torusGeometry, material);
box.name = `${handleName}.handle`;
box.scale.set(20, 20, 20);
box.lookAt(new THREE.Vector3(...handle.alignment));
node.add(box);
handle.translateNode = box;
let outline = new THREE.Mesh(outlineGeometry, outlineMaterial);
outline.name = `${handleName}.outline`;
outline.scale.set(1, 1, 1);
outline.renderOrder = 0;
box.add(outline);
let pickVolume = new THREE.Mesh(pickGeometry, pickMaterial);
pickVolume.name = `${handleName}.pick_volume`;
pickVolume.scale.set(1, 1, 1);
pickVolume.handle = handleName;
box.add(pickVolume);
this.pickVolumes.push(pickVolume);
node.setOpacity = (target) => {
let opacity = {x: material.opacity};
let t = new TWEEN.Tween(opacity).to({x: target}, 100);
t.onUpdate(() => {
box.visible = opacity.x > 0;
pickVolume.visible = opacity.x > 0;
material.opacity = opacity.x;
outlineMaterial.opacity = opacity.x;
pickMaterial.opacity = opacity.x * 0.5;
});
t.start();
};
//pickVolume.addEventListener("mouseover", (e) => {
// //let a = this.viewer.scene.getActiveCamera().getWorldDirection(new THREE.Vector3()).dot(pickVolume.getWorldDirection(new THREE.Vector3()));
// console.log(pickVolume.getWorldDirection(new THREE.Vector3()));
//});
pickVolume.addEventListener("drag", (e) => {this.dragRotationHandle(e)});
pickVolume.addEventListener("drop", (e) => {this.dropRotationHandle(e)});
}
}
dragRotationHandle(e){
let drag = e.drag;
let handle = this.activeHandle;
let camera = this.viewer.scene.getActiveCamera();
if(!handle){
return
};
let localNormal = new THREE.Vector3(...handle.alignment);
let n = new THREE.Vector3();
n.copy(new THREE.Vector4(...localNormal.toArray(), 0).applyMatrix4(handle.node.matrixWorld));
n.normalize();
if (!drag.intersectionStart){
//this.viewer.scene.scene.remove(this.debug);
//this.debug = new THREE.Object3D();
//this.viewer.scene.scene.add(this.debug);
//Utils.debugSphere(this.debug, drag.location, 3, 0xaaaaaa);
//let debugEnd = drag.location.clone().add(n.clone().multiplyScalar(20));
//Utils.debugLine(this.debug, drag.location, debugEnd, 0xff0000);
drag.intersectionStart = drag.location;
drag.objectStart = drag.object.getWorldPosition(new THREE.Vector3());
drag.handle = handle;
let plane = new THREE.Plane().setFromNormalAndCoplanarPoint(n, drag.intersectionStart);
drag.dragPlane = plane;
drag.pivot = drag.intersectionStart;
}else{
handle = drag.handle;
}
this.dragging = true;
let mouse = drag.end;
let domElement = this.viewer.renderer.domElement;
let ray = Utils.mouseToRay(mouse, camera, domElement.clientWidth, domElement.clientHeight);
let I = ray.intersectPlane(drag.dragPlane, new THREE.Vector3());
if (I) {
let center = this.scene.getWorldPosition(new THREE.Vector3());
let from = drag.pivot;
let to = I;
let v1 = from.clone().sub(center).normalize();
let v2 = to.clone().sub(center).normalize();
let angle = Math.acos(v1.dot(v2));
let sign = Math.sign(v1.cross(v2).dot(n));
angle = angle * sign;
if (Number.isNaN(angle)) {
return;
}
let normal = new THREE.Vector3(...handle.alignment);
for (let selection of this.selection) {
selection.rotateOnAxis(normal, angle);
selection.dispatchEvent({
type: "orientation_changed",
object: selection
});
}
drag.pivot = I;
}
}
dropRotationHandle(e){
this.dragging = false;
this.setActiveHandle(null);
}
dragTranslationHandle(e){
let drag = e.drag;
let handle = this.activeHandle;
let camera = this.viewer.scene.getActiveCamera();
if(!drag.intersectionStart && handle){
drag.intersectionStart = drag.location;
drag.objectStart = drag.object.getWorldPosition(new THREE.Vector3());
let start = drag.intersectionStart;
let dir = new THREE.Vector4(...handle.alignment, 0).applyMatrix4(this.scene.matrixWorld);
let end = new THREE.Vector3().addVectors(start, dir);
let line = new THREE.Line3(start.clone(), end.clone());
drag.line = line;
let camOnLine = line.closestPointToPoint(camera.position, false, new THREE.Vector3());
let normal = new THREE.Vector3().subVectors(camera.position, camOnLine);
let plane = new THREE.Plane().setFromNormalAndCoplanarPoint(normal, drag.intersectionStart);
drag.dragPlane = plane;
drag.pivot = drag.intersectionStart;
}else{
handle = drag.handle;
}
this.dragging = true;
{
let mouse = drag.end;
let domElement = this.viewer.renderer.domElement;
let ray = Utils.mouseToRay(mouse, camera, domElement.clientWidth, domElement.clientHeight);
let I = ray.intersectPlane(drag.dragPlane, new THREE.Vector3());
if (I) {
let iOnLine = drag.line.closestPointToPoint(I, false, new THREE.Vector3());
let diff = new THREE.Vector3().subVectors(iOnLine, drag.pivot);
for (let selection of this.selection) {
selection.position.add(diff);
selection.dispatchEvent({
type: "position_changed",
object: selection
});
}
drag.pivot = drag.pivot.add(diff);
}
}
}
dropTranslationHandle(e){
this.dragging = false;
this.setActiveHandle(null);
}
dropScaleHandle(e){
this.dragging = false;
this.setActiveHandle(null);
}
dragScaleHandle(e){
let drag = e.drag;
let handle = this.activeHandle;
let camera = this.viewer.scene.getActiveCamera();
if(!drag.intersectionStart){
drag.intersectionStart = drag.location;
drag.objectStart = drag.object.getWorldPosition(new THREE.Vector3());
drag.handle = handle;
let start = drag.intersectionStart;
let dir = new THREE.Vector4(...handle.alignment, 0).applyMatrix4(this.scene.matrixWorld);
let end = new THREE.Vector3().addVectors(start, dir);
let line = new THREE.Line3(start.clone(), end.clone());
drag.line = line;
let camOnLine = line.closestPointToPoint(camera.position, false, new THREE.Vector3());
let normal = new THREE.Vector3().subVectors(camera.position, camOnLine);
let plane = new THREE.Plane().setFromNormalAndCoplanarPoint(normal, drag.intersectionStart);
drag.dragPlane = plane;
drag.pivot = drag.intersectionStart;
//Utils.debugSphere(viewer.scene.scene, drag.pivot, 0.05);
}else{
handle = drag.handle;
}
this.dragging = true;
{
let mouse = drag.end;
let domElement = this.viewer.renderer.domElement;
let ray = Utils.mouseToRay(mouse, camera, domElement.clientWidth, domElement.clientHeight);
let I = ray.intersectPlane(drag.dragPlane, new THREE.Vector3());
if (I) {
let iOnLine = drag.line.closestPointToPoint(I, false, new THREE.Vector3());
let direction = handle.alignment.reduce( (a, v) => a + v, 0);
let toObjectSpace = this.selection[0].matrixWorld.clone().invert();
let iOnLineOS = iOnLine.clone().applyMatrix4(toObjectSpace);
let pivotOS = drag.pivot.clone().applyMatrix4(toObjectSpace);
let diffOS = new THREE.Vector3().subVectors(iOnLineOS, pivotOS);
let dragDirectionOS = diffOS.clone().normalize();
if(iOnLine.distanceTo(drag.pivot) === 0){
dragDirectionOS.set(0, 0, 0);
}
let dragDirection = dragDirectionOS.dot(new THREE.Vector3(...handle.alignment));
let diff = new THREE.Vector3().subVectors(iOnLine, drag.pivot);
let diffScale = new THREE.Vector3(...handle.alignment).multiplyScalar(diff.length() * direction * dragDirection);
let diffPosition = diff.clone().multiplyScalar(0.5);
for (let selection of this.selection) {
selection.scale.add(diffScale);
selection.scale.x = Math.max(0.1, selection.scale.x);
selection.scale.y = Math.max(0.1, selection.scale.y);
selection.scale.z = Math.max(0.1, selection.scale.z);
selection.position.add(diffPosition);
selection.dispatchEvent({
type: "position_changed",
object: selection
});
selection.dispatchEvent({
type: "scale_changed",
object: selection
});
}
drag.pivot.copy(iOnLine);
//Utils.debugSphere(viewer.scene.scene, drag.pivot, 0.05);
}
}
}
setActiveHandle(handle){
if(this.dragging){
return;
}
if(this.activeHandle === handle){
return;
}
this.activeHandle = handle;
if(handle === null){
for(let handleName of Object.keys(this.handles)){
let handle = this.handles[handleName];
handle.node.setOpacity(0);
}
}
for(let handleName of Object.keys(this.focusHandles)){
let handle = this.focusHandles[handleName];
if(this.activeHandle === handle){
handle.node.setOpacity(1.0);
}else{
handle.node.setOpacity(0.4)
}
}
for(let handleName of Object.keys(this.translationHandles)){
let handle = this.translationHandles[handleName];
if(this.activeHandle === handle){
handle.node.setOpacity(1.0);
}else{
handle.node.setOpacity(0.4)
}
}
for(let handleName of Object.keys(this.rotationHandles)){
let handle = this.rotationHandles[handleName];
//if(this.activeHandle === handle){
// handle.node.setOpacity(1.0);
//}else{
// handle.node.setOpacity(0.4)
//}
handle.node.setOpacity(0.4);
}
for(let handleName of Object.keys(this.scaleHandles)){
let handle = this.scaleHandles[handleName];
if(this.activeHandle === handle){
handle.node.setOpacity(1.0);
let relatedFocusHandle = this.focusHandles[handle.name.replace("scale", "focus")];
let relatedFocusNode = relatedFocusHandle.node;
relatedFocusNode.setOpacity(0.4);
for(let translationHandleName of Object.keys(this.translationHandles)){
let translationHandle = this.translationHandles[translationHandleName];
translationHandle.node.setOpacity(0.4);
}
//let relatedTranslationHandle = this.translationHandles[
// handle.name.replace("scale", "translation").replace(/[+-]/g, "")];
//let relatedTranslationNode = relatedTranslationHandle.node;
//relatedTranslationNode.setOpacity(0.4);
}else{
handle.node.setOpacity(0.4)
}
}
if(handle){
handle.node.setOpacity(1.0);
}
}
update () {
if(this.selection.length === 1){
this.scene.visible = true;
this.scene.updateMatrix();
this.scene.updateMatrixWorld();
let selected = this.selection[0];
let world = selected.matrixWorld;
let camera = this.viewer.scene.getActiveCamera();
let domElement = this.viewer.renderer.domElement;
let mouse = this.viewer.inputHandler.mouse;
let center = selected.boundingBox.getCenter(new THREE.Vector3()).clone().applyMatrix4(selected.matrixWorld);
this.scene.scale.copy(selected.boundingBox.getSize(new THREE.Vector3()).multiply(selected.scale));
this.scene.position.copy(center);
this.scene.rotation.copy(selected.rotation);
this.scene.updateMatrixWorld();
{
// adjust scale of components
for(let handleName of Object.keys(this.handles)){
let handle = this.handles[handleName];
let node = handle.node;
let handlePos = node.getWorldPosition(new THREE.Vector3());
let distance = handlePos.distanceTo(camera.position);
let pr = Utils.projectedRadius(1, camera, distance, domElement.clientWidth, domElement.clientHeight);
let ws = node.parent.getWorldScale(new THREE.Vector3());
let s = (7 / pr);
let scale = new THREE.Vector3(s, s, s).divide(ws);
let rot = new THREE.Matrix4().makeRotationFromEuler(node.rotation);
let rotInv = rot.clone().invert();
scale.applyMatrix4(rotInv);
scale.x = Math.abs(scale.x);
scale.y = Math.abs(scale.y);
scale.z = Math.abs(scale.z);
node.scale.copy(scale);
}
// adjust rotation handles
if(!this.dragging){
let tWorld = this.scene.matrixWorld;
let tObject = tWorld.clone().invert();
let camObjectPos = camera.getWorldPosition(new THREE.Vector3()).applyMatrix4(tObject);
let x = this.rotationHandles["rotation.x"].node.rotation;
let y = this.rotationHandles["rotation.y"].node.rotation;
let z = this.rotationHandles["rotation.z"].node.rotation;
x.order = "ZYX";
y.order = "ZYX";
let above = camObjectPos.z > 0;
let below = !above;
let PI_HALF = Math.PI / 2;
if(above){
if(camObjectPos.x > 0 && camObjectPos.y > 0){
x.x = 1 * PI_HALF;
y.y = 3 * PI_HALF;
z.z = 0 * PI_HALF;
}else if(camObjectPos.x < 0 && camObjectPos.y > 0){
x.x = 1 * PI_HALF;
y.y = 2 * PI_HALF;
z.z = 1 * PI_HALF;
}else if(camObjectPos.x < 0 && camObjectPos.y < 0){
x.x = 2 * PI_HALF;
y.y = 2 * PI_HALF;
z.z = 2 * PI_HALF;
}else if(camObjectPos.x > 0 && camObjectPos.y < 0){
x.x = 2 * PI_HALF;
y.y = 3 * PI_HALF;
z.z = 3 * PI_HALF;
}
}else if(below){
if(camObjectPos.x > 0 && camObjectPos.y > 0){
x.x = 0 * PI_HALF;
y.y = 0 * PI_HALF;
z.z = 0 * PI_HALF;
}else if(camObjectPos.x < 0 && camObjectPos.y > 0){
x.x = 0 * PI_HALF;
y.y = 1 * PI_HALF;
z.z = 1 * PI_HALF;
}else if(camObjectPos.x < 0 && camObjectPos.y < 0){
x.x = 3 * PI_HALF;
y.y = 1 * PI_HALF;
z.z = 2 * PI_HALF;
}else if(camObjectPos.x > 0 && camObjectPos.y < 0){
x.x = 3 * PI_HALF;
y.y = 0 * PI_HALF;
z.z = 3 * PI_HALF;
}
}
}
{
let ray = Utils.mouseToRay(mouse, camera, domElement.clientWidth, domElement.clientHeight);
let raycaster = new THREE.Raycaster(ray.origin, ray.direction);
let intersects = raycaster.intersectObjects(this.pickVolumes.filter(v => v.visible), true);
if(intersects.length > 0){
let I = intersects[0];
let handleName = I.object.handle;
this.setActiveHandle(this.handles[handleName]);
}else{
this.setActiveHandle(null);
}
}
//
for(let handleName of Object.keys(this.scaleHandles)){
let handle = this.handles[handleName];
let node = handle.node;
let alignment = handle.alignment;
}
}
}else{
this.scene.visible = false;
}
}
};