UNPKG

@sauskylark/potree

Version:

WebGL point cloud viewer

168 lines (127 loc) 4.51 kB
import * as THREE from "../../libs/three.js/build/three.module.js"; import {Volume, BoxVolume} from "./Volume.js"; import {Utils} from "../utils.js"; import { EventDispatcher } from "../EventDispatcher.js"; export class VolumeTool extends EventDispatcher{ constructor (viewer) { super(); this.viewer = viewer; this.renderer = viewer.renderer; this.addEventListener('start_inserting_volume', e => { this.viewer.dispatchEvent({ type: 'cancel_insertions' }); }); this.scene = new THREE.Scene(); this.scene.name = 'scene_volume'; this.viewer.inputHandler.registerInteractiveScene(this.scene); this.onRemove = e => { this.scene.remove(e.volume); }; this.onAdd = e => { this.scene.add(e.volume); }; for(let volume of viewer.scene.volumes){ this.onAdd({volume: volume}); } this.viewer.inputHandler.addEventListener('delete', e => { let volumes = e.selection.filter(e => (e instanceof Volume)); volumes.forEach(e => this.viewer.scene.removeVolume(e)); }); viewer.addEventListener("update", this.update.bind(this)); viewer.addEventListener("render.pass.scene", e => this.render(e)); viewer.addEventListener("scene_changed", this.onSceneChange.bind(this)); viewer.scene.addEventListener('volume_added', this.onAdd); viewer.scene.addEventListener('volume_removed', this.onRemove); } onSceneChange(e){ if(e.oldScene){ e.oldScene.removeEventListeners('volume_added', this.onAdd); e.oldScene.removeEventListeners('volume_removed', this.onRemove); } e.scene.addEventListener('volume_added', this.onAdd); e.scene.addEventListener('volume_removed', this.onRemove); } startInsertion (args = {}) { let volume; if(args.type){ volume = new args.type(); }else{ volume = new BoxVolume(); } volume.clip = args.clip || false; volume.name = args.name || 'Volume'; this.dispatchEvent({ type: 'start_inserting_volume', volume: volume }); this.viewer.scene.addVolume(volume); this.scene.add(volume); let cancel = { callback: null }; let drag = e => { let camera = this.viewer.scene.getActiveCamera(); let I = Utils.getMousePointCloudIntersection( e.drag.end, this.viewer.scene.getActiveCamera(), this.viewer, this.viewer.scene.pointclouds, {pickClipped: false}); if (I) { volume.position.copy(I.location); let wp = volume.getWorldPosition(new THREE.Vector3()).applyMatrix4(camera.matrixWorldInverse); // let pp = new THREE.Vector4(wp.x, wp.y, wp.z).applyMatrix4(camera.projectionMatrix); let w = Math.abs((wp.z / 5)); volume.scale.set(w, w, w); } }; let drop = e => { volume.removeEventListener('drag', drag); volume.removeEventListener('drop', drop); cancel.callback(); }; cancel.callback = e => { volume.removeEventListener('drag', drag); volume.removeEventListener('drop', drop); this.viewer.removeEventListener('cancel_insertions', cancel.callback); }; volume.addEventListener('drag', drag); volume.addEventListener('drop', drop); this.viewer.addEventListener('cancel_insertions', cancel.callback); this.viewer.inputHandler.startDragging(volume); return volume; } update(){ if (!this.viewer.scene) { return; } let camera = this.viewer.scene.getActiveCamera(); let renderAreaSize = this.viewer.renderer.getSize(new THREE.Vector2()); let clientWidth = renderAreaSize.width; let clientHeight = renderAreaSize.height; let volumes = this.viewer.scene.volumes; for (let volume of volumes) { let label = volume.label; { let distance = label.position.distanceTo(camera.position); let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight); let scale = (70 / pr); label.scale.set(scale, scale, scale); } let calculatedVolume = volume.getVolume(); calculatedVolume = calculatedVolume / Math.pow(this.viewer.lengthUnit.unitspermeter, 3) * Math.pow(this.viewer.lengthUnitDisplay.unitspermeter, 3); //convert to cubic meters then to the cubic display unit let text = Utils.addCommas(calculatedVolume.toFixed(3)) + ' ' + this.viewer.lengthUnitDisplay.code + '\u00B3'; label.setText(text); } } render(params){ const renderer = this.viewer.renderer; const oldTarget = renderer.getRenderTarget(); if(params.renderTarget){ renderer.setRenderTarget(params.renderTarget); } renderer.render(this.scene, this.viewer.scene.getActiveCamera()); renderer.setRenderTarget(oldTarget); } }