UNPKG

@sauskylark/potree

Version:

WebGL point cloud viewer

291 lines (243 loc) 9.38 kB
import * as THREE from "../../libs/three.js/build/three.module.js"; export class ClipVolume extends THREE.Object3D{ constructor(args){ super(); this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1; this.name = "clip_volume_" + this.constructor.counter; let alpha = args.alpha || 0; let beta = args.beta || 0; let gamma = args.gamma || 0; this.rotation.x = alpha; this.rotation.y = beta; this.rotation.z = gamma; this.clipOffset = 0.001; this.clipRotOffset = 1; let boxGeometry = new THREE.BoxGeometry(1, 1, 1); boxGeometry.computeBoundingBox(); 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)); boxFrameGeometry.colors.push(new THREE.Vector3(1, 1, 1)); } let planeFrameGeometry = new THREE.Geometry(); { // middle line planeFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, 0.0)); planeFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, 0.0)); planeFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, 0.0)); planeFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, 0.0)); planeFrameGeometry.vertices.push(new THREE.Vector3(-0.5, 0.5, 0.0)); planeFrameGeometry.vertices.push(new THREE.Vector3(0.5, 0.5, 0.0)); planeFrameGeometry.vertices.push(new THREE.Vector3(-0.5, -0.5, 0.0)); planeFrameGeometry.vertices.push(new THREE.Vector3(0.5, -0.5, 0.0)); } this.dimension = new THREE.Vector3(1, 1, 1); this.material = new THREE.MeshBasicMaterial( { color: 0x00ff00, transparent: true, opacity: 0.3, depthTest: true, depthWrite: false} ); this.box = new THREE.Mesh(boxGeometry, this.material); this.box.geometry.computeBoundingBox(); this.boundingBox = this.box.geometry.boundingBox; this.add(this.box); this.frame = new THREE.LineSegments( boxFrameGeometry, new THREE.LineBasicMaterial({color: 0x000000})); this.add(this.frame); this.planeFrame = new THREE.LineSegments( planeFrameGeometry, new THREE.LineBasicMaterial({color: 0xff0000})); this.add(this.planeFrame); // set default thickness this.setScaleZ(0.1); // create local coordinate system let createArrow = (name, direction, color) => { let material = new THREE.MeshBasicMaterial({ color: color, depthTest: false, depthWrite: false}); let shaftGeometry = new THREE.Geometry(); shaftGeometry.vertices.push(new THREE.Vector3(0, 0, 0)); shaftGeometry.vertices.push(new THREE.Vector3(0, 1, 0)); let shaftMaterial = new THREE.LineBasicMaterial({ color: color, depthTest: false, depthWrite: false, transparent: true }); let shaft = new THREE.Line(shaftGeometry, shaftMaterial); shaft.name = name + "_shaft"; let headGeometry = new THREE.CylinderGeometry(0, 0.04, 0.1, 10, 1, false); let headMaterial = material; let head = new THREE.Mesh(headGeometry, headMaterial); head.name = name + "_head"; head.position.y = 1; let arrow = new THREE.Object3D(); arrow.name = name; arrow.add(shaft); arrow.add(head); return arrow; }; this.arrowX = createArrow("arrow_x", new THREE.Vector3(1, 0, 0), 0xFF0000); this.arrowY = createArrow("arrow_y", new THREE.Vector3(0, 1, 0), 0x00FF00); this.arrowZ = createArrow("arrow_z", new THREE.Vector3(0, 0, 1), 0x0000FF); this.arrowX.rotation.z = -Math.PI / 2; this.arrowZ.rotation.x = Math.PI / 2; this.arrowX.visible = false; this.arrowY.visible = false; this.arrowZ.visible = false; this.add(this.arrowX); this.add(this.arrowY); this.add(this.arrowZ); { // event listeners this.addEventListener("ui_select", e => { this.arrowX.visible = true; this.arrowY.visible = true; this.arrowZ.visible = true; }); this.addEventListener("ui_deselect", e => { this.arrowX.visible = false; this.arrowY.visible = false; this.arrowZ.visible = false; }); this.addEventListener("select", e => { let scene_header = $("#" + this.name + " .scene_header"); if(!scene_header.next().is(":visible")) { scene_header.click(); } }); this.addEventListener("deselect", e => { let scene_header = $("#" + this.name + " .scene_header"); if(scene_header.next().is(":visible")) { scene_header.click(); } }); } this.update(); }; setClipOffset(offset) { this.clipOffset = offset; } setClipRotOffset(offset) { this.clipRotOffset = offset; } setScaleX(x) { this.box.scale.x = x; this.frame.scale.x = x; this.planeFrame.scale.x = x; } setScaleY(y) { this.box.scale.y = y; this.frame.scale.y = y; this.planeFrame.scale.y = y; } setScaleZ(z) { this.box.scale.z = z; this.frame.scale.z = z; this.planeFrame.scale.z = z; } offset(args) { let cs = args.cs || null; let axis = args.axis || null; let dir = args.dir || null; if(!cs || !axis || !dir) return; if(axis === "x") { if(cs === "local") { this.position.add(this.localX.clone().multiplyScalar(dir * this.clipOffset)); } else if(cs === "global") { this.position.x = this.position.x + dir * this.clipOffset; } }else if(axis === "y") { if(cs === "local") { this.position.add(this.localY.clone().multiplyScalar(dir * this.clipOffset)); } else if(cs === "global") { this.position.y = this.position.y + dir * this.clipOffset; } }else if(axis === "z") { if(cs === "local") { this.position.add(this.localZ.clone().multiplyScalar(dir * this.clipOffset)); } else if(cs === "global") { this.position.z = this.position.z + dir * this.clipOffset; } } this.dispatchEvent({"type": "clip_volume_changed", "viewer": viewer, "volume": this}); } rotate(args) { let cs = args.cs || null; let axis = args.axis || null; let dir = args.dir || null; if(!cs || !axis || !dir) return; if(cs === "local") { if(axis === "x") { this.rotateOnAxis(new THREE.Vector3(1, 0, 0), dir * this.clipRotOffset * Math.PI / 180); } else if(axis === "y") { this.rotateOnAxis(new THREE.Vector3(0, 1, 0), dir * this.clipRotOffset * Math.PI / 180); } else if(axis === "z") { this.rotateOnAxis(new THREE.Vector3(0, 0, 1), dir * this.clipRotOffset * Math.PI / 180); } } else if(cs === "global") { let rotaxis = new THREE.Vector4(1, 0, 0, 0); if(axis === "y") { rotaxis = new THREE.Vector4(0, 1, 0, 0); } else if(axis === "z") { rotaxis = new THREE.Vector4(0, 0, 1, 0); } this.updateMatrixWorld(); let invM = newthis.matrixWorld.clone().invert(); rotaxis = rotaxis.applyMatrix4(invM).normalize(); rotaxis = new THREE.Vector3(rotaxis.x, rotaxis.y, rotaxis.z); this.rotateOnAxis(rotaxis, dir * this.clipRotOffset * Math.PI / 180); } this.updateLocalSystem(); this.dispatchEvent({"type": "clip_volume_changed", "viewer": viewer, "volume": this}); } update(){ this.boundingBox = this.box.geometry.boundingBox; this.boundingSphere = this.boundingBox.getBoundingSphere(new THREE.Sphere()); this.box.visible = false; this.updateLocalSystem(); }; updateLocalSystem() { // extract local coordinate axes let rotQuat = this.getWorldQuaternion(); this.localX = new THREE.Vector3(1, 0, 0).applyQuaternion(rotQuat).normalize(); this.localY = new THREE.Vector3(0, 1, 0).applyQuaternion(rotQuat).normalize(); this.localZ = new THREE.Vector3(0, 0, 1).applyQuaternion(rotQuat).normalize(); } raycast(raycaster, intersects){ let is = []; this.box.raycast(raycaster, is); if(is.length > 0){ let I = is[0]; intersects.push({ distance: I.distance, object: this, point: I.point.clone() }); } }; };