potree
Version:
WebGL point cloud viewer - WORK IN PROGRESS
217 lines (164 loc) • 6.07 kB
JavaScript
Potree.TranslationTool = function (camera) {
THREE.Object3D.call(this);
var scope = this;
this.camera = camera;
this.geometry = new THREE.Geometry();
this.material = new THREE.MeshBasicMaterial({ color: Math.random() * 0xffffff });
this.STATE = {
DEFAULT: 0,
TRANSLATE_X: 1,
TRANSLATE_Y: 2,
TRANSLATE_Z: 3
};
this.parts = {
ARROW_X: {name: 'arrow_x', object: undefined, color: new THREE.Color(0xff0000), state: this.STATE.TRANSLATE_X},
ARROW_Y: {name: 'arrow_y', object: undefined, color: new THREE.Color(0x00ff00), state: this.STATE.TRANSLATE_Y},
ARROW_Z: {name: 'arrow_z', object: undefined, color: new THREE.Color(0x0000ff), state: this.STATE.TRANSLATE_Z}
};
this.state = this.STATE.DEFAULT;
this.highlighted = null;
this.targets = null;
this.build = function () {
var arrowX = scope.createArrow(scope.parts.ARROW_X, scope.parts.ARROW_X.color);
arrowX.rotation.z = -Math.PI / 2;
var arrowY = scope.createArrow(scope.parts.ARROW_Y, scope.parts.ARROW_Y.color);
var arrowZ = scope.createArrow(scope.parts.ARROW_Z, scope.parts.ARROW_Z.color);
arrowZ.rotation.x = -Math.PI / 2;
scope.add(arrowX);
scope.add(arrowY);
scope.add(arrowZ);
var boxXY = scope.createBox(new THREE.Color(0xffff00));
boxXY.scale.z = 0.02;
boxXY.position.set(0.5, 0.5, 0);
var boxXZ = scope.createBox(new THREE.Color(0xff00ff));
boxXZ.scale.y = 0.02;
boxXZ.position.set(0.5, 0, -0.5);
var boxYZ = scope.createBox(new THREE.Color(0x00ffff));
boxYZ.scale.x = 0.02;
boxYZ.position.set(0, 0.5, -0.5);
scope.add(boxXY);
scope.add(boxXZ);
scope.add(boxYZ);
scope.parts.ARROW_X.object = arrowX;
scope.parts.ARROW_Y.object = arrowY;
scope.parts.ARROW_Z.object = arrowZ;
scope.scale.multiplyScalar(5);
};
this.createBox = function (color) {
var boxGeometry = new THREE.BoxGeometry(1, 1, 1);
var boxMaterial = new THREE.MeshBasicMaterial({color: color, transparent: true, opacity: 0.5});
var box = new THREE.Mesh(boxGeometry, boxMaterial);
return box;
};
this.createArrow = function (partID, color) {
var material = new THREE.MeshBasicMaterial({color: color});
var shaftGeometry = new THREE.CylinderGeometry(0.1, 0.1, 3, 10, 1, false);
var shaftMatterial = material;
var shaft = new THREE.Mesh(shaftGeometry, shaftMatterial);
shaft.position.y = 1.5;
var headGeometry = new THREE.CylinderGeometry(0, 0.3, 1, 10, 1, false);
var headMaterial = material;
var head = new THREE.Mesh(headGeometry, headMaterial);
head.position.y = 3;
var arrow = new THREE.Object3D();
arrow.add(shaft);
arrow.add(head);
arrow.partID = partID;
arrow.material = material;
return arrow;
};
this.setHighlighted = function (partID) {
if (partID === undefined) {
if (scope.highlighted) {
scope.highlighted.object.material.color = scope.highlighted.color;
scope.highlighted = undefined;
}
return;
} else if (scope.highlighted !== undefined && scope.highlighted !== partID) {
scope.highlighted.object.material.color = scope.highlighted.color;
}
scope.highlighted = partID;
partID.object.material.color = new THREE.Color(0xffff00);
};
this.getHoveredObject = function (mouse) {
var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
vector.unproject(scope.camera);
var raycaster = new THREE.Raycaster();
raycaster.ray.set(scope.camera.position, vector.sub(scope.camera.position).normalize());
var intersections = raycaster.intersectObject(scope, true);
if (intersections.length === 0) {
scope.setHighlighted(undefined);
return undefined;
}
var I = intersections[0];
var partID = I.object.parent.partID;
return partID;
};
this.onMouseMove = function (event) {
var mouse = event.normalizedPosition;
if (scope.state === scope.STATE.DEFAULT) {
scope.setHighlighted(scope.getHoveredObject(mouse));
} else if (scope.state === scope.STATE.TRANSLATE_X || scope.state === scope.STATE.TRANSLATE_Y || scope.state === scope.STATE.TRANSLATE_Z) {
var origin = scope.start.lineStart.clone();
var direction = scope.start.lineEnd.clone().sub(scope.start.lineStart);
direction.normalize();
var mousePoint = new THREE.Vector3(mouse.x, mouse.y);
var directionDistance = new THREE.Vector3().subVectors(mousePoint, origin).dot(direction);
var pointOnLine = direction.clone().multiplyScalar(directionDistance).add(origin);
pointOnLine.unproject(scope.camera);
var diff = pointOnLine.clone().sub(scope.position);
scope.position.copy(pointOnLine);
for (var i = 0; i < scope.targets.length; i++) {
var target = scope.targets[0];
target.position.add(diff);
}
event.signal.halt();
}
};
this.onMouseDown = function (event) {
if (scope.state === scope.STATE.DEFAULT) {
var hoveredObject = scope.getHoveredObject(event.normalizedPosition, scope.camera);
if (hoveredObject) {
scope.state = hoveredObject.state;
var lineStart = scope.position.clone();
var lineEnd;
if (scope.state === scope.STATE.TRANSLATE_X) {
lineEnd = scope.position.clone();
lineEnd.x += 2;
} else if (scope.state === scope.STATE.TRANSLATE_Y) {
lineEnd = scope.position.clone();
lineEnd.y += 2;
} else if (scope.state === scope.STATE.TRANSLATE_Z) {
lineEnd = scope.position.clone();
lineEnd.z -= 2;
}
lineStart.project(scope.camera);
lineEnd.project(scope.camera);
scope.start = {
mouse: event.normalizedPosition,
lineStart: lineStart,
lineEnd: lineEnd
};
event.signal.halt();
}
}
};
this.onMouseUp = function (event) {
scope.setHighlighted();
scope.state = scope.STATE.DEFAULT;
};
this.setTargets = function (targets) {
scope.targets = targets;
if (scope.targets.length === 0) {
return;
}
// TODO calculate centroid of all targets
var centroid = targets[0].position.clone();
// for(var i = 0; i < targets.length; i++){
// var target = targets[i];
// }
scope.position.copy(centroid);
};
this.build();
};
Potree.TranslationTool.prototype = Object.create(THREE.Object3D.prototype);