12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978 |
- import * as THREE from "../../libs/three.js/build/three.module.js";
- import {ClipTask, ClipMethod, CameraMode, LengthUnits, ElevationGradientRepeat} from "../defines.js";
- import {Renderer} from "../PotreeRenderer.js";
- import {PotreeRenderer} from "./PotreeRenderer.js";
- import {EDLRenderer} from "./EDLRenderer.js";
- import {HQSplatRenderer} from "./HQSplatRenderer.js";
- import {Scene} from "./Scene.js";
- import {ClippingTool} from "../utils/ClippingTool.js";
- import {TransformationTool} from "../utils/TransformationTool.js";
- import {Utils} from "../utils.js";
- import {MapView} from "./map.js";
- import {MapViewer} from "./map/MapViewer.js";
- import {ProfileWindow, ProfileWindowController} from "./profile.js";
- import {BoxVolume} from "../utils/Volume.js";
- import {Features} from "../Features.js";
- import {Message} from "../utils/Message.js";
- import {Sidebar} from "./sidebar.js";
- import {AnnotationTool} from "../utils/AnnotationTool.js";
- import {MeasuringTool} from "../utils/MeasuringTool.js";
- import {ProfileTool} from "../utils/ProfileTool.js";
- import {VolumeTool} from "../utils/VolumeTool.js";
- import {InputHandler} from "../navigation/InputHandler.js";
- import {NavigationCube} from "./NavigationCube.js";
- import {Compass} from "../utils/Compass.js";
- import {OrbitControls} from "../navigation/OrbitControls.js";
- import {FirstPersonControls} from "../navigation/FirstPersonControls.js";
- import {EarthControls} from "../navigation/EarthControls.js";
- import {DeviceOrientationControls} from "../navigation/DeviceOrientationControls.js";
- import {VRControls} from "../navigation/VRControls.js";
- import { ClassificationScheme } from "../materials/ClassificationScheme.js";
- import { VRButton } from '../../libs/three.js/extra/VRButton.js';
- import {transitions, easing, lerp} from '../utils/transitions.js'
- import JSON5 from "../../libs/json5-2.1.3/json5.mjs";
- import CursorDeal from '../utils/CursorDeal'
- import Common from '../utils/Common'
- import {Clip} from '../modules/clipModel/Clip'
- import {Alignment} from "../modules/datasetAlignment/Alignment.js";
- import {SiteModel} from "../modules/siteModel/SiteModel.js";
- import Magnifier from "../utils/Magnifier.js";
- import Reticule from "../navigation/Reticule.js";
- import Viewport from "./Viewport.js"
- import {ViewerBase} from "./viewerBase.js"
-
- import SplitScreen from '../utils/SplitScreen'
- import cameraLight from "../utils/cameraLight.js";
- import math from "../utils/math.js";
-
- import {UoMService} from '../utils/UnitConvert'
- import {RouteGuider} from '../navigation/RouteGuider'
- let mapArea;
- export class Viewer extends ViewerBase{
-
- constructor(domElement, mapArea_, args = {}){
- super(domElement,args);
- window.viewer = this
- this.modules = { //add
- Clip : Clip,
- Alignment : Alignment,
- SiteModel : SiteModel,
- RouteGuider : new RouteGuider,
-
- }
-
-
-
- //add --------
- this.navigateMode = 'free' // 'panorama'; 'free'自由模式是只显示点云或者未进入到漫游点,
- this.isEdit = true
- this.waitQueue = []
- this.unitConvert = new UoMService();
- mapArea = mapArea_
- //-------------
-
-
-
- this.guiLoaded = false;
- this.guiLoadTasks = [];
- this.onVrListeners = [];
-
- this.messages = [];
- this.elMessages = $(`
- <div id="message_listing"
- style="position: absolute; z-index: 1000; left: 10px; bottom: 10px">
- </div>`);
- $(domElement).append(this.elMessages);
-
-
-
- try{
-
- if(!Potree.settings.isOfficial)
- { // generate missing dom hierarchy
- if ($(domElement).find('#potree_map').length === 0) {
- let potreeMap = $(`
- <div id="potree_map" class="mapBox" style="position: absolute; left: 50px; top: 50px; width: 400px; height: 400px; display: none">
- <div id="potree_map_header" style="position: absolute; width: 100%; height: 25px; top: 0px; background-color: rgba(0,0,0,0.5); z-index: 1000; border-top-left-radius: 3px; border-top-right-radius: 3px;">
- </div>
- <div id="potree_map_content" class="map" style="position: absolute; z-index: 100; top: 25px; width: 100%; height: calc(100% - 25px); border: 2px solid rgba(0,0,0,0.5); box-sizing: border-box;"></div>
- </div>
- `);
- $(domElement).append(potreeMap);
- }
- if ($(domElement).find('#potree_description').length === 0) {
- let potreeDescription = $(`<div id="potree_description" class="potree_info_text"></div>`);
- $(domElement).append(potreeDescription);
- }
- if ($(domElement).find('#potree_annotations').length === 0) {
- let potreeAnnotationContainer = $(`
- <div id="potree_annotation_container"
- style="position: absolute; z-index: 100000; width: 100%; height: 100%; pointer-events: none;"></div>`);
- $(domElement).append(potreeAnnotationContainer);
- }
- if ($(domElement).find('#potree_quick_buttons').length === 0) {
- let potreeMap = $(`
- <div id="potree_quick_buttons" class="quick_buttons_container" style="">
- </div>
- `);
-
- $(domElement).append(potreeMap);
- }
-
- //add
- {
-
- if(!mapArea){
- $(domElement).append($("<div id='potree_labels'></div>"))
-
- mapArea = $("<div id='mapGaode'></div>")
- $(domElement).append(mapArea)
- mapArea = mapArea[0]
- }
-
- }
-
-
- let domRoot = this.renderer.domElement.parentElement;
- let elAttach = $("<input type='button' value='test'></input>");
- elAttach.css({
- position : "absolute",
- right : '10%',
- bottom: '20px',
- zIndex: "10000",
- fontSize:'1em', color:"black",
- background:'rgba(255,255,255,0.8)',
- })
- let state = false
- elAttach.on("click", () => {
- window.buttonFunction && window.buttonFunction()
- });
- domRoot.appendChild(elAttach[0]);
-
-
-
-
- }
-
-
- this.pointCloudLoadedCallback = args.onPointCloudLoaded || function () {};
- // if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
- // defaultSettings.navigation = "Orbit";
- // }
- this.server = null;
- this.fov = 60;
- this.isFlipYZ = false;
- this.useDEMCollisions = false;
- this.generateDEM = false;
- this.minNodeSize = 30;
- this.edlStrength = 1.0;
- this.edlRadius = 1.4;
- this.edlOpacity = 1.0;
- this.useEDL = false;
- this.description = "";
- this.classifications = ClassificationScheme.DEFAULT;
- this.moveSpeed = 10;
- this.lengthUnit = LengthUnits.METER;
- this.lengthUnitDisplay = LengthUnits.METER;
- this.showBoundingBox = false;
- this.showAnnotations = true;
- this.freeze = false;
- this.clipTask = ClipTask.HIGHLIGHT;
- this.clipMethod = ClipMethod.INSIDE_ANY;
- this.elevationGradientRepeat = ElevationGradientRepeat.CLAMP;
- this.filterReturnNumberRange = [0, 7];
- this.filterNumberOfReturnsRange = [0, 7];
- this.filterGPSTimeRange = [-Infinity, Infinity];
- this.filterPointSourceIDRange = [0, 65535];
- this.potreeRenderer = null;
- this.edlRenderer = null;
- this.pRenderer = null;
- this.scene = null;
- this.sceneVR = null;
- this.overlay = null;
- this.overlayCamera = null;
- this.inputHandler = null;
- this.controls = null;
- this.clippingTool = null;
- this.transformationTool = null;
- this.navigationCube = null;
- this.compass = null;
-
- this.skybox = null;
- this.clock = new THREE.Clock();
- this.background = null;
-
-
-
- if(args.noDragAndDrop){
-
- }else{
- this.initDragAndDrop();
- }
- if(typeof Stats !== "undefined"){
- this.stats = new Stats();
- this.stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
- document.body.appendChild( this.stats.dom );
- }
- {
- let canvas = this.renderer.domElement;
- canvas.addEventListener("webglcontextlost", (e) => {
- console.log(e);
- this.postMessage("WebGL context lost. \u2639");
- let gl = this.renderer.getContext();
- let error = gl.getError();
- console.log(error);
- }, false);
- }
- {
- this.overlay = new THREE.Scene();
- this.overlayCamera = new THREE.OrthographicCamera(
- 0, 1,
- 1, 0,
- -1000, 1000
- );
- }
-
- this.pRenderer = new Renderer(this.renderer);
-
- {
- let near = 2.5;
- let far = 10.0;
- let fov = 90;
-
- this.shadowTestCam = new THREE.PerspectiveCamera(90, 1, near, far);
- this.shadowTestCam.position.set(3.50, -2.80, 8.561);
- this.shadowTestCam.lookAt(new THREE.Vector3(0, 0, 4.87));
- }
-
- let scene = new Scene(this.renderer);
-
- { // create VR scene
- this.sceneVR = new THREE.Scene();
- // let texture = new THREE.TextureLoader().load(`${Potree.resourcePath}/images/vr_controller_help.jpg`);
- // let plane = new THREE.PlaneBufferGeometry(1, 1, 1, 1);
- // let infoMaterial = new THREE.MeshBasicMaterial({map: texture});
- // let infoNode = new THREE.Mesh(plane, infoMaterial);
- // infoNode.position.set(-0.5, 1, 0);
- // infoNode.scale.set(0.4, 0.3, 1);
- // infoNode.lookAt(0, 1, 0)
- // this.sceneVR.add(infoNode);
- // window.infoNode = infoNode;
- }
- this.setScene(scene);
- {
- this.inputHandler = new InputHandler(this, this.scene.scene);
- //this.inputHandler.setScene(this.scene);
- //this.inputHandler.addInputListener(this);//add
-
-
-
- this.clippingTool = new ClippingTool(this);
- this.transformationTool = new TransformationTool(this);
- this.navigationCube = new NavigationCube(this);
- this.navigationCube.visible = false;
- this.compass = new Compass(this);
-
-
- //add----------
- this.magnifier = new Magnifier(this);
- this.reticule = new Reticule(this)
- this.scene.scene.add(this.magnifier)
- this.scene.scene.add(this.reticule)
- this.mainViewport = new Viewport( this.scene.view, this.scene.cameraP, {
- left:0, bottom:0, width:1, height: 1, name:'MainView'
- })
- this.viewports = [this.mainViewport]
-
-
- this.mapViewer = new MapViewer(mapArea/* $('#mapGaode')[0] */)
- CursorDeal.init(this)//ADD
-
- this.modules.SiteModel.init()
-
- //-----------
-
-
- this.createControls();
- this.clippingTool.setScene(this.scene);
-
- let onPointcloudAdded = (e) => {
- if (this.scene.pointclouds.length === 1) {
- let speed = e.pointcloud.boundingBox.getSize(new THREE.Vector3()).length();
- speed = speed / 2000;
- this.setMoveSpeed(speed);
- }
- };
- let onVolumeRemoved = (e) => {
- this.inputHandler.deselect(e.volume);
- };
- this.addEventListener('scene_changed', (e) => {
- this.inputHandler.setScene(e.scene);
- this.clippingTool.setScene(this.scene);
-
- if(!e.scene.hasEventListener("pointcloud_added", onPointcloudAdded)){
- e.scene.addEventListener("pointcloud_added", onPointcloudAdded);
- }
- if(!e.scene.hasEventListener("volume_removed", onPointcloudAdded)){
- e.scene.addEventListener("volume_removed", onVolumeRemoved);
- }
-
- });
- this.scene.addEventListener("volume_removed", onVolumeRemoved);
- this.scene.addEventListener('pointcloud_added', onPointcloudAdded);
- }
- { // set defaults
- this.setFOV(60);
- this.setEDLEnabled(false);
- this.setEDLRadius(1.4);
- this.setEDLStrength(0.4);
- this.setEDLOpacity(1.0);
- this.setClipTask(ClipTask.HIGHLIGHT);
- this.setClipMethod(ClipMethod.INSIDE_ANY);
- this.setPointBudget(1*1000*1000);
- this.setShowBoundingBox(false);
- this.setFreeze(false);
- this.setControls(this.fpControls/* orbitControls */);
- this.setBackground('gradient');
- this.scaleFactor = 1;
- this.loadSettingsFromURL();
- }
- // start rendering!
- //if(args.useDefaultRenderLoop === undefined || args.useDefaultRenderLoop === true){
- //requestAnimationFrame(this.loop.bind(this));
- //}
-
- this.renderer.setAnimationLoop(this.loop.bind(this));
- this.loadGUI = this.loadGUI.bind(this);
- this.annotationTool = new AnnotationTool(this);
- this.measuringTool = new MeasuringTool(this);
- this.profileTool = new ProfileTool(this);
- this.volumeTool = new VolumeTool(this);
- }catch(e){
- this.onCrash(e);
- }
-
- {//add
- let pointDensity = ''
- Object.defineProperty(Potree.settings , "pointDensity",{
- get: function() {
- return pointDensity
- },
- set: (density)=>{
- if(pointDensity != density){
- var config = Potree.config.pointDensity[density];
- viewer.setPointBudget(config.pointBudget );
- Potree.maxPointLevel = config.maxLevel
- viewer.scene.pointclouds.forEach(e=>{
- e.maxLevel = config.maxLevel
- })
- }
- }
- })
- }
- {
-
- let cameraFar = Potree.settings.cameraFar
- Object.defineProperty(Potree.settings , "cameraFar",{
- get: function() {
- return cameraFar
- },
- set: (far)=>{
- if(far != cameraFar){
- if(Potree.settings.displayMode != 'showPanos'){
- this.mainViewport.camera.far = far;
- this.mainViewport.camera.updateProjectionMatrix()
- }
- }
- }
- })
-
-
-
- }
-
-
- }
- onCrash(error){
- $(this.renderArea).empty();
- if ($(this.renderArea).find('#potree_failpage').length === 0) {
- let elFailPage = $(`
- <div id="#potree_failpage" class="potree_failpage">
-
- <h1>Potree Encountered An Error </h1>
- <p>
- This may happen if your browser or graphics card is not supported.
- <br>
- We recommend to use
- <a href="https://www.google.com/chrome/browser" target="_blank" style="color:initial">Chrome</a>
- or
- <a href="https://www.mozilla.org/" target="_blank">Firefox</a>.
- </p>
- <p>
- Please also visit <a href="http://webglreport.com/" target="_blank">webglreport.com</a> and
- check whether your system supports WebGL.
- </p>
- <p>
- If you are already using one of the recommended browsers and WebGL is enabled,
- consider filing an issue report at <a href="https://github.com/potree/potree/issues" target="_blank">github</a>,<br>
- including your operating system, graphics card, browser and browser version, as well as the
- error message below.<br>
- Please do not report errors on unsupported browsers.
- </p>
- <pre id="potree_error_console" style="width: 100%; height: 100%"></pre>
-
- </div>`);
- let elErrorMessage = elFailPage.find('#potree_error_console');
- elErrorMessage.html(error.stack);
- $(this.renderArea).append(elFailPage);
- }
- throw error;
- }
- // ------------------------------------------------------------------------------------
- // Viewer API
- // ------------------------------------------------------------------------------------
- setScene (scene) {
- if (scene === this.scene) {
- return;
- }
- let oldScene = this.scene;
- this.scene = scene;
- this.dispatchEvent({
- type: 'scene_changed',
- oldScene: oldScene,
- scene: scene
- });
- { // Annotations
- $('.annotation').detach();
- // for(let annotation of this.scene.annotations){
- // this.renderArea.appendChild(annotation.domElement[0]);
- // }
- this.scene.annotations.traverse(annotation => {
- this.renderArea.appendChild(annotation.domElement[0]);
- });
- if (!this.onAnnotationAdded) {
- this.onAnnotationAdded = e => {
- // console.log("annotation added: " + e.annotation.title);
- e.annotation.traverse(node => {
- $("#potree_annotation_container").append(node.domElement);
- //this.renderArea.appendChild(node.domElement[0]);
- node.scene = this.scene;
- });
- };
- }
- if (oldScene) {
- oldScene.annotations.removeEventListener('annotation_added', this.onAnnotationAdded);
- }
- this.scene.annotations.addEventListener('annotation_added', this.onAnnotationAdded);
- }
- };
- setControls(controls/* , setSpeed */){
- if (controls !== this.controls) {
- if (this.controls) {
- this.controls.setEnable(false)
- //this.inputHandler.removeInputListener(this.controls);
- this.controls.moveSpeed = this.moveSpeed; //记录 (因为orbit的radius很大,转为firstPerson时要缩小)
- }
- this.controls = controls;
- controls.moveSpeed && this.setMoveSpeed(controls.moveSpeed) //add
-
- this.controls.setEnable(true)
-
- //this.inputHandler.addInputListener(this.controls);
- }
- }
- getControls () {
- if(this.renderer.xr.isPresenting){
- return this.vrControls;
- }else{
- return this.controls;
- }
-
- }
- getMinNodeSize () {
- return this.minNodeSize;
- };
- setMinNodeSize (value) {
- if (this.minNodeSize !== value) {
- this.minNodeSize = value;
- this.dispatchEvent({'type': 'minnodesize_changed', 'viewer': this});
- }
- };
- getBackground () {
- return this.background;
- }
- setBackground(bg){
- if (this.background === bg) {
- return;
- }
- if(bg === "skybox"){
- this.skybox = Utils.loadSkybox(new URL(Potree.resourcePath + '/textures/skybox2/').href);
- }
- this.background = bg;
- this.backgroundOpacity = 1//add
- this.dispatchEvent({'type': 'background_changed', 'viewer': this});
- }
- setDescription (value) {
- this.description = value;
-
- $('#potree_description').html(value);
- //$('#potree_description').text(value);
- }
- getDescription(){
- return this.description;
- }
- setShowBoundingBox (value) {
- if (this.showBoundingBox !== value) {
- this.showBoundingBox = value;
- this.dispatchEvent({'type': 'show_boundingbox_changed', 'viewer': this});
- }
- };
- getShowBoundingBox () {
- return this.showBoundingBox;
- };
-
- setMoveSpeed (value) {
- if (this.getMoveSpeed() !== value) {
- this.mainViewport.setMoveSpeed(value)
- this.dispatchEvent({'type': 'move_speed_changed', 'viewer': this, 'speed': value});
- }
- };
- getMoveSpeed () {
- return this.mainViewport.moveSpeed;
- };
- setWeightClassification (w) {
- for (let i = 0; i < this.scene.pointclouds.length; i++) {
- this.scene.pointclouds[i].material.weightClassification = w;
- this.dispatchEvent({'type': 'attribute_weights_changed' + i, 'viewer': this});
- }
- };
- setFreeze (value) {
- value = Boolean(value);
- if (this.freeze !== value) {
- this.freeze = value;
- this.dispatchEvent({'type': 'freeze_changed', 'viewer': this});
- }
- };
- getFreeze () {
- return this.freeze;
- };
- getClipTask(){
- return this.clipTask;
- }
- getClipMethod(){
- return this.clipMethod;
- }
- setClipTask(value){
- if(this.clipTask !== value){
- this.clipTask = value;
- this.dispatchEvent({
- type: "cliptask_changed",
- viewer: this});
- }
- }
- setClipMethod(value){
- if(this.clipMethod !== value){
- this.clipMethod = value;
-
- this.dispatchEvent({
- type: "clipmethod_changed",
- viewer: this});
- }
- }
- setElevationGradientRepeat(value){
- if(this.elevationGradientRepeat !== value){
- this.elevationGradientRepeat = value;
- this.dispatchEvent({
- type: "elevation_gradient_repeat_changed",
- viewer: this});
- }
- }
- setPointBudget (value) {
- if (Potree.pointBudget !== value) {
- Potree.pointBudget = parseInt(value);
- this.dispatchEvent({'type': 'point_budget_changed', 'viewer': this});
- }
- };
- getPointBudget () {
- return Potree.pointBudget;
- };
- setShowAnnotations (value) {
- if (this.showAnnotations !== value) {
- this.showAnnotations = value;
- this.dispatchEvent({'type': 'show_annotations_changed', 'viewer': this});
- }
- }
- getShowAnnotations () {
- return this.showAnnotations;
- }
-
- setDEMCollisionsEnabled(value){
- if(this.useDEMCollisions !== value){
- this.useDEMCollisions = value;
- this.dispatchEvent({'type': 'use_demcollisions_changed', 'viewer': this});
- };
- };
- getDEMCollisionsEnabled () {
- return this.useDEMCollisions;
- };
- setEDLEnabled (value) {
- value = Boolean(value) && Features.SHADER_EDL.isSupported();
- if (this.useEDL !== value) {
- this.useEDL = value;
- this.dispatchEvent({'type': 'use_edl_changed', 'viewer': this});
- }
- };
- getEDLEnabled () {
- return this.useEDL;
- };
- setEDLRadius (value) {
- if (this.edlRadius !== value) {
- this.edlRadius = value;
- this.dispatchEvent({'type': 'edl_radius_changed', 'viewer': this});
- }
- };
- getEDLRadius () {
- return this.edlRadius;
- };
- setEDLStrength (value) {
- if (this.edlStrength !== value) {
- this.edlStrength = value;
- this.dispatchEvent({'type': 'edl_strength_changed', 'viewer': this});
- }
- };
- getEDLStrength () {
- return this.edlStrength;
- };
- setEDLOpacity (value) {
- if (this.edlOpacity !== value) {
- this.edlOpacity = value;
- this.dispatchEvent({'type': 'edl_opacity_changed', 'viewer': this});
- }
- };
- getEDLOpacity () {
- return this.edlOpacity;
- };
- setFOV (value) {
- if (this.fov !== value) {
- this.fov = value;
- this.scene.cameraP.fov = this.fov;
- this.scene.cameraP.updateProjectionMatrix()
- this.dispatchEvent({'type': 'fov_changed', 'viewer': this});
- }
- };
- getFOV () {
- return this.fov;
- };
- disableAnnotations () {
- this.scene.annotations.traverse(annotation => {
- annotation.domElement.css('pointer-events', 'none');
- // return annotation.visible;
- });
- };
- enableAnnotations () {
- this.scene.annotations.traverse(annotation => {
- annotation.domElement.css('pointer-events', 'auto');
- // return annotation.visible;
- });
- }
- setClassifications(classifications){
- this.classifications = classifications;
- this.dispatchEvent({'type': 'classifications_changed', 'viewer': this});
- }
- setClassificationVisibility (key, value) {
- if (!this.classifications[key]) {
- this.classifications[key] = {visible: value, name: 'no name'};
- this.dispatchEvent({'type': 'classification_visibility_changed', 'viewer': this});
- } else if (this.classifications[key].visible !== value) {
- this.classifications[key].visible = value;
- this.dispatchEvent({'type': 'classification_visibility_changed', 'viewer': this});
- }
- }
- toggleAllClassificationsVisibility(){
- let numVisible = 0;
- let numItems = 0;
- for(const key of Object.keys(this.classifications)){
- if(this.classifications[key].visible){
- numVisible++;
- }
- numItems++;
- }
- let visible = true;
- if(numVisible === numItems){
- visible = false;
- }
- let somethingChanged = false;
- for(const key of Object.keys(this.classifications)){
- if(this.classifications[key].visible !== visible){
- this.classifications[key].visible = visible;
- somethingChanged = true;
- }
- }
- if(somethingChanged){
- this.dispatchEvent({'type': 'classification_visibility_changed', 'viewer': this});
- }
- }
- setFilterReturnNumberRange(from, to){
- this.filterReturnNumberRange = [from, to];
- this.dispatchEvent({'type': 'filter_return_number_range_changed', 'viewer': this});
- }
- setFilterNumberOfReturnsRange(from, to){
- this.filterNumberOfReturnsRange = [from, to];
- this.dispatchEvent({'type': 'filter_number_of_returns_range_changed', 'viewer': this});
- }
- setFilterGPSTimeRange(from, to){
- this.filterGPSTimeRange = [from, to];
- this.dispatchEvent({'type': 'filter_gps_time_range_changed', 'viewer': this});
- }
- setFilterPointSourceIDRange(from, to){
- this.filterPointSourceIDRange = [from, to]
- this.dispatchEvent({'type': 'filter_point_source_id_range_changed', 'viewer': this});
- }
- setLengthUnit (value) {
- switch (value) {
- case 'm':
- this.lengthUnit = LengthUnits.METER;
- this.lengthUnitDisplay = LengthUnits.METER;
- break;
- case 'ft':
- this.lengthUnit = LengthUnits.FEET;
- this.lengthUnitDisplay = LengthUnits.FEET;
- break;
- case 'in':
- this.lengthUnit = LengthUnits.INCH;
- this.lengthUnitDisplay = LengthUnits.INCH;
- break;
- }
- this.dispatchEvent({ 'type': 'length_unit_changed', 'viewer': this, value: value});
- };
- setLengthUnitAndDisplayUnit(lengthUnitValue, lengthUnitDisplayValue) {
- switch (lengthUnitValue) {
- case 'm':
- this.lengthUnit = LengthUnits.METER;
- break;
- case 'ft':
- this.lengthUnit = LengthUnits.FEET;
- break;
- case 'in':
- this.lengthUnit = LengthUnits.INCH;
- break;
- }
- switch (lengthUnitDisplayValue) {
- case 'm':
- this.lengthUnitDisplay = LengthUnits.METER;
- break;
- case 'ft':
- this.lengthUnitDisplay = LengthUnits.FEET;
- break;
- case 'in':
- this.lengthUnitDisplay = LengthUnits.INCH;
- break;
- }
- this.dispatchEvent({ 'type': 'length_unit_changed', 'viewer': this, value: lengthUnitValue });
- };
- zoomTo(node, factor, animationDuration = 0){
- let view = this.scene.view;
- let camera = this.scene.cameraP.clone();
- camera.rotation.copy(this.scene.cameraP.rotation);
- camera.rotation.order = "ZXY";
- camera.rotation.x = Math.PI / 2 + view.pitch;
- camera.rotation.z = view.yaw;
- camera.updateMatrix();
- camera.updateMatrixWorld();
- camera.zoomTo(node, factor);
- let bs;
- if (node.boundingSphere) {
- bs = node.boundingSphere;
- } else if (node.geometry && node.geometry.boundingSphere) {
- bs = node.geometry.boundingSphere;
- } else {
- bs = node.boundingBox.getBoundingSphere(new THREE.Sphere());
- }
- bs = bs.clone().applyMatrix4(node.matrixWorld);
- let startPosition = view.position.clone();
- let endPosition = camera.position.clone();
- let startTarget = view.getPivot();
- let endTarget = bs.center;
- let startRadius = view.radius;
- let endRadius = endPosition.distanceTo(endTarget);
- let easing = TWEEN.Easing.Quartic.Out;
- { // animate camera position
- let pos = startPosition.clone();
- let tween = new TWEEN.Tween(pos).to(endPosition, animationDuration);
- tween.easing(easing);
- tween.onUpdate(() => {
- view.position.copy(pos);
- });
- tween.start();
- }
- { // animate camera target
- let target = startTarget.clone();
- let tween = new TWEEN.Tween(target).to(endTarget, animationDuration);
- tween.easing(easing);
- tween.onUpdate(() => {
- view.lookAt(target);
- });
- tween.onComplete(() => {
- view.lookAt(target);
- this.dispatchEvent({type: 'focusing_finished', target: this});
- });
- this.dispatchEvent({type: 'focusing_started', target: this});
- tween.start();
- }
- };
- moveToGpsTimeVicinity(time){
- const result = Potree.Utils.findClosestGpsTime(time, viewer);
- const box = result.node.pointcloud.deepestNodeAt(result.position).getBoundingBox();
- const diameter = box.min.distanceTo(box.max);
- const camera = this.scene.getActiveCamera();
- const offset = camera.getWorldDirection(new THREE.Vector3()).multiplyScalar(diameter);
- const newCamPos = result.position.clone().sub(offset);
- this.scene.view.position.copy(newCamPos);
- this.scene.view.lookAt(result.position);
- }
- showAbout () {
- $(function () {
- $('#about-panel').dialog();
- });
- };
-
- getGpsTimeExtent(){
- const range = [Infinity, -Infinity];
- for(const pointcloud of this.scene.pointclouds){
- const attributes = pointcloud.pcoGeometry.pointAttributes.attributes;
- const aGpsTime = attributes.find(a => a.name === "gps-time");
- if(aGpsTime){
- range[0] = Math.min(range[0], aGpsTime.range[0]);
- range[1] = Math.max(range[1], aGpsTime.range[1]);
- }
- }
- return range;
- }
- fitToScreen (factor = 1, animationDuration = 0) {
- let box = this.getBoundingBox(this.scene.pointclouds);
- let node = new THREE.Object3D();
- node.boundingBox = box;
- this.zoomTo(node, factor, animationDuration);
- this.controls.stop();
- };
- toggleNavigationCube() {
- this.navigationCube.visible = !this.navigationCube.visible;
- }
- /* setView(pos, view) {
- if(!pos) return;
-
- switch(pos) {
- case "F":
- this.setFrontView(view);
- break;
- case "B":
- this.setBackView(view);
- break;
- case "L":
- this.setLeftView(view);
- break;
- case "R":
- this.setRightView(view);
- break;
- case "U":
- this.setTopView(view);
- break;
- case "D":
- this.setBottomView(view);
- break;
- }
- } */
-
- setTopView(view){
- view = view || this.scene.view
- view.setCubeView("Top")
- this.fitToScreen();
- };
-
- setBottomView(){
- this.scene.view.yaw = -Math.PI;
- this.scene.view.pitch = Math.PI / 2;
-
- this.fitToScreen();
- };
- setFrontView(view){
- view = view || this.scene.view
- view.yaw = 0;
- view.pitch = 0;
- this.fitToScreen();
- };
-
- setBackView(view){
- view = view || this.scene.view
- view.yaw = Math.PI;
- view.pitch = 0;
-
- this.fitToScreen();
- };
- setLeftView(){
- this.scene.view.yaw = -Math.PI / 2;
- this.scene.view.pitch = 0;
- this.fitToScreen();
- };
- setRightView () {
- this.scene.view.yaw = Math.PI / 2;
- this.scene.view.pitch = 0;
- this.fitToScreen();
- };
- flipYZ () {
- this.isFlipYZ = !this.isFlipYZ;
- // TODO flipyz
- console.log('TODO');
- }
-
- setCameraMode(mode){
- this.scene.cameraMode = mode;
- for(let pointcloud of this.scene.pointclouds) {
- pointcloud.material.useOrthographicCamera = mode == CameraMode.ORTHOGRAPHIC;
- }
- }
- getProjection(){
- const pointcloud = this.scene.pointclouds[0];
- if(pointcloud){
- return pointcloud.projection;
- }else{
- return null;
- }
- }
- async loadProject(url){
- const response = await fetch(url);
- if(response.ok){
- const text = await response.text();
- const json = JSON5.parse(text);
- // const json = JSON.parse(text);
- if(json.type === "Potree"){
- Potree.loadProject(viewer, json);
- }
-
- }else{
- console.warn("未能加载:"+url )
- }
-
- }
- saveProject(){
- return Potree.saveProject(this);
- }
-
- loadSettingsFromURL(){
- if(Utils.getParameterByName("pointSize")){
- this.setPointSize(parseFloat(Utils.getParameterByName("pointSize")));
- }
-
- if(Utils.getParameterByName("FOV")){
- this.setFOV(parseFloat(Utils.getParameterByName("FOV")));
- }
-
- if(Utils.getParameterByName("opacity")){
- this.setOpacity(parseFloat(Utils.getParameterByName("opacity")));
- }
-
- if(Utils.getParameterByName("edlEnabled")){
- let enabled = Utils.getParameterByName("edlEnabled") === "true";
- this.setEDLEnabled(enabled);
- }
- if (Utils.getParameterByName('edlRadius')) {
- this.setEDLRadius(parseFloat(Utils.getParameterByName('edlRadius')));
- }
- if (Utils.getParameterByName('edlStrength')) {
- this.setEDLStrength(parseFloat(Utils.getParameterByName('edlStrength')));
- }
- if (Utils.getParameterByName('pointBudget')) {
- this.setPointBudget(parseFloat(Utils.getParameterByName('pointBudget')));
- }
- if (Utils.getParameterByName('showBoundingBox')) {
- let enabled = Utils.getParameterByName('showBoundingBox') === 'true';
- if (enabled) {
- this.setShowBoundingBox(true);
- } else {
- this.setShowBoundingBox(false);
- }
- }
- if (Utils.getParameterByName('material')) {
- let material = Utils.getParameterByName('material');
- this.setMaterial(material);
- }
- if (Utils.getParameterByName('pointSizing')) {
- let sizing = Utils.getParameterByName('pointSizing');
- this.setPointSizing(sizing);
- }
- if (Utils.getParameterByName('quality')) {
- let quality = Utils.getParameterByName('quality');
- this.setQuality(quality);
- }
- if (Utils.getParameterByName('position')) {
- let value = Utils.getParameterByName('position');
- value = value.replace('[', '').replace(']', '');
- let tokens = value.split(';');
- let x = parseFloat(tokens[0]);
- let y = parseFloat(tokens[1]);
- let z = parseFloat(tokens[2]);
- this.scene.view.position.set(x, y, z);
- }
- if (Utils.getParameterByName('target')) {
- let value = Utils.getParameterByName('target');
- value = value.replace('[', '').replace(']', '');
- let tokens = value.split(';');
- let x = parseFloat(tokens[0]);
- let y = parseFloat(tokens[1]);
- let z = parseFloat(tokens[2]);
- this.scene.view.lookAt(new THREE.Vector3(x, y, z));
- }
- if (Utils.getParameterByName('background')) {
- let value = Utils.getParameterByName('background');
- this.setBackground(value);
- }
- // if(Utils.getParameterByName("elevationRange")){
- // let value = Utils.getParameterByName("elevationRange");
- // value = value.replace("[", "").replace("]", "");
- // let tokens = value.split(";");
- // let x = parseFloat(tokens[0]);
- // let y = parseFloat(tokens[1]);
- //
- // this.setElevationRange(x, y);
- // //this.scene.view.target.set(x, y, z);
- // }
- };
- // ------------------------------------------------------------------------------------
- // Viewer Internals
- // ------------------------------------------------------------------------------------
- createControls () {
- { // create FIRST PERSON CONTROLS
- this.fpControls = new FirstPersonControls(this, this.mainViewport);
- this.fpControls.enabled = false;
- this.fpControls.addEventListener('start', this.disableAnnotations.bind(this));
- this.fpControls.addEventListener('end', this.enableAnnotations.bind(this));
- this.addEventListener("loadPointCloudDone", ()=>{
- let boundPlane = new THREE.Box3()
- boundPlane.expandByPoint(this.bound.boundingBox.min.clone())//最低高度为bound的最低
- boundPlane.expandByPoint(this.bound.boundingBox.max.clone().setZ(this.bound.center.z))//最高高度为bound的中心高度
- FirstPersonControls.boundPlane = boundPlane
- FirstPersonControls.standardSpeed = THREE.Math.clamp( Math.sqrt(this.bound.boundSize.length() )/ 100 , 0.02,0.5); //在这个boundPlane中的速度
- })
-
- }
- // { // create GEO CONTROLS
- // this.geoControls = new GeoControls(this.scene.camera, this.renderer.domElement);
- // this.geoControls.enabled = false;
- // this.geoControls.addEventListener("start", this.disableAnnotations.bind(this));
- // this.geoControls.addEventListener("end", this.enableAnnotations.bind(this));
- // this.geoControls.addEventListener("move_speed_changed", (event) => {
- // this.setMoveSpeed(this.geoControls.moveSpeed);
- // });
- // }
- { // create ORBIT CONTROLS
- this.orbitControls = new OrbitControls(this);
- this.orbitControls.enabled = false;
- this.orbitControls.addEventListener('start', this.disableAnnotations.bind(this));
- this.orbitControls.addEventListener('end', this.enableAnnotations.bind(this));
- }
- { // create EARTH CONTROLS
- this.earthControls = new EarthControls(this);
- this.earthControls.enabled = false;
- this.earthControls.addEventListener('start', this.disableAnnotations.bind(this));
- this.earthControls.addEventListener('end', this.enableAnnotations.bind(this));
- }
- { // create DEVICE ORIENTATION CONTROLS
- this.deviceControls = new DeviceOrientationControls(this);
- this.deviceControls.enabled = false;
- this.deviceControls.addEventListener('start', this.disableAnnotations.bind(this));
- this.deviceControls.addEventListener('end', this.enableAnnotations.bind(this));
- }
- { // create VR CONTROLS
- this.vrControls = new VRControls(this);
- this.vrControls.enabled = false;
- this.vrControls.addEventListener('start', this.disableAnnotations.bind(this));
- this.vrControls.addEventListener('end', this.enableAnnotations.bind(this));
- }
- };
- toggleSidebar () {
- let renderArea = $('#potree_render_area');
- let isVisible = renderArea.css('left') !== '0px';
- if (isVisible) {
- renderArea.css('left', '0px');
- } else {
- renderArea.css('left', '300px');
- }
- };
- toggleMap () {
- // let map = $('#potree_map');
- // map.toggle(100);
- if (this.mapView) {
- this.mapView.toggle();
- }
- };
- onGUILoaded(callback){
- if(this.guiLoaded){
- callback();
- }else{
- this.guiLoadTasks.push(callback);
- }
- }
- promiseGuiLoaded(){
- return new Promise( resolve => {
- if(this.guiLoaded){
- resolve();
- }else{
- this.guiLoadTasks.push(resolve);
- }
-
- });
- }
- loadGUI(callback){
- if(callback){
- this.onGUILoaded(callback);
- }
- let viewer = this;
- let sidebarContainer = $('#potree_sidebar_container');
- sidebarContainer.load(new URL(Potree.scriptPath + '/sidebar.html').href, () => {
- sidebarContainer.css('width', '300px');
- sidebarContainer.css('height', '100%');
- let imgMenuToggle = document.createElement('img');
- imgMenuToggle.src = new URL(Potree.resourcePath + '/icons/menu_button.svg').href;
- imgMenuToggle.onclick = this.toggleSidebar;
- imgMenuToggle.classList.add('potree_menu_toggle');
- let imgMapToggle = document.createElement('img');
- imgMapToggle.src = new URL(Potree.resourcePath + '/icons/map_icon.png').href;
- imgMapToggle.style.display = 'none';
- imgMapToggle.onclick = e => { this.toggleMap(); };
- imgMapToggle.id = 'potree_map_toggle';
-
- let elButtons = $("#potree_quick_buttons").get(0);
- elButtons.append(imgMenuToggle);
- elButtons.append(imgMapToggle);
- /*
- VRButton.createButton(this.renderer).then(vrButton => {
- if(vrButton == null){
- console.log("VR not supported or active.");
- return;
- }
- this.renderer.xr.enabled = true;
- let element = vrButton.element;
- element.style.position = "";
- element.style.bottom = "";
- element.style.left = "";
- element.style.margin = "4px";
- element.style.fontSize = "100%";
- element.style.width = "2.5em";
- element.style.height = "2.5em";
- element.style.padding = "0";
- element.style.textShadow = "black 2px 2px 2px";
- element.style.display = "block";
- elButtons.append(element);
- vrButton.onStart(() => {
- this.dispatchEvent({type: "vr_start"});
- });
- vrButton.onEnd(() => {
- this.dispatchEvent({type: "vr_end"});
- });
- });
-
- this.mapView = new MapView(this);
- this.mapView.init(); */
-
- i18n.init({
- lng: 'en',
- resGetPath: Potree.resourcePath + '/lang/__lng__/__ns__.json',
- preload: ['en', 'fr', 'de', 'jp', 'se', 'es', 'zh'],
- getAsync: true,
- debug: false
- }, function (t) {
- // Start translation once everything is loaded
- $('body').i18n();
- });
- $(() => {
- //initSidebar(this);
- let sidebar = new Sidebar(this);
- sidebar.init();
- this.sidebar = sidebar;
- //if (callback) {
- // $(callback);
- //}
- let elProfile = $('<div>').load(new URL(Potree.scriptPath + '/profile.html').href, () => {
- $(document.body).append(elProfile.children());
- this.profileWindow = new ProfileWindow(this);
- this.profileWindowController = new ProfileWindowController(this);
- $('#profile_window').draggable({
- handle: $('#profile_titlebar'),
- containment: $(document.body)
- });
- $('#profile_window').resizable({
- containment: $(document.body),
- handles: 'n, e, s, w'
- });
- $(() => {
- this.guiLoaded = true;
- for(let task of this.guiLoadTasks){
- task();
- }
- });
- });
-
- });
-
- });
- return this.promiseGuiLoaded();
- }
- setLanguage (lang) {
- i18n.setLng(lang);
- $('body').i18n();
- }
- setServer (server) {
- this.server = server;
- }
- initDragAndDrop(){
- function allowDrag(e) {
- e.dataTransfer.dropEffect = 'copy';
- e.preventDefault();
- }
- let dropHandler = async (event) => {
- console.log(event);
- event.preventDefault();
- for(const item of event.dataTransfer.items){
- console.log(item);
- if(item.kind !== "file"){
- continue;
- }
- const file = item.getAsFile();
- const isJson = file.name.toLowerCase().endsWith(".json");
- const isGeoPackage = file.name.toLowerCase().endsWith(".gpkg");
- if(isJson){
- try{
- const text = await file.text();
- const json = JSON.parse(text);
- if(json.type === "Potree"){
- Potree.loadProject(viewer, json);
- }
- }catch(e){
- console.error("failed to parse the dropped file as JSON");
- console.error(e);
- }
- }else if(isGeoPackage){
- const hasPointcloud = viewer.scene.pointclouds.length > 0;
- if(!hasPointcloud){
- let msg = "At least one point cloud is needed that specifies the ";
- msg += "coordinate reference system before loading vector data.";
- console.error(msg);
- }else{
- proj4.defs("WGS84", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
- proj4.defs("pointcloud", this.getProjection());
- let transform = proj4("WGS84", "pointcloud");
- const buffer = await file.arrayBuffer();
- const params = {
- transform: transform,
- source: file.name,
- };
-
- const geo = await Potree.GeoPackageLoader.loadBuffer(buffer, params);
- viewer.scene.addGeopackage(geo);
- }
- }
-
- }
- };
- $("body")[0].addEventListener("dragenter", allowDrag);
- $("body")[0].addEventListener("dragover", allowDrag);
- $("body")[0].addEventListener("drop", dropHandler);
- }
-
-
-
- updateAnnotations () {
- if(!this.visibleAnnotations){
- this.visibleAnnotations = new Set();
- }
- this.scene.annotations.updateBounds();
- this.scene.cameraP.updateMatrixWorld();
- this.scene.cameraO.updateMatrixWorld();
-
- let distances = [];
- let renderAreaSize = this.renderer.getSize(new THREE.Vector2());
- let viewer = this;
- let visibleNow = [];
- this.scene.annotations.traverse(annotation => {
- if (annotation === this.scene.annotations) {
- return true;
- }
- if (!annotation.visible) {
- return false;
- }
- annotation.scene = this.scene;
- let element = annotation.domElement;
- let position = annotation.position.clone();
- position.add(annotation.offset);
- if (!position) {
- position = annotation.boundingBox.getCenter(new THREE.Vector3());
- }
- let distance = viewer.scene.cameraP.position.distanceTo(position);
- let radius = annotation.boundingBox.getBoundingSphere(new THREE.Sphere()).radius;
- let screenPos = new THREE.Vector3();
- let screenSize = 0;
- {
- // SCREEN POS
- screenPos.copy(position).project(this.scene.getActiveCamera());
- screenPos.x = renderAreaSize.x * (screenPos.x + 1) / 2;
- screenPos.y = renderAreaSize.y * (1 - (screenPos.y + 1) / 2);
- // SCREEN SIZE
- if(viewer.scene.cameraMode == CameraMode.PERSPECTIVE) {
- let fov = Math.PI * viewer.scene.cameraP.fov / 180;
- let slope = Math.tan(fov / 2.0);
- let projFactor = 0.5 * renderAreaSize.y / (slope * distance);
- screenSize = radius * projFactor;
- } else {
- screenSize = Utils.projectedRadiusOrtho(radius, viewer.scene.cameraO.projectionMatrix, renderAreaSize.x, renderAreaSize.y);
- }
- }
- element.css("left", screenPos.x + "px");
- element.css("top", screenPos.y + "px");
- //element.css("display", "block");
- let zIndex = 10000000 - distance * (10000000 / this.scene.cameraP.far);
- if(annotation.descriptionVisible){
- zIndex += 10000000;
- }
- element.css("z-index", parseInt(zIndex));
- if(annotation.children.length > 0){
- let expand = screenSize > annotation.collapseThreshold || annotation.boundingBox.containsPoint(this.scene.getActiveCamera().position);
- annotation.expand = expand;
- if (!expand) {
- //annotation.display = (screenPos.z >= -1 && screenPos.z <= 1);
- let inFrustum = (screenPos.z >= -1 && screenPos.z <= 1);
- if(inFrustum){
- visibleNow.push(annotation);
- }
- }
- return expand;
- } else {
- //annotation.display = (screenPos.z >= -1 && screenPos.z <= 1);
- let inFrustum = (screenPos.z >= -1 && screenPos.z <= 1);
- if(inFrustum){
- visibleNow.push(annotation);
- }
- }
-
- });
- let notVisibleAnymore = new Set(this.visibleAnnotations);
- for(let annotation of visibleNow){
- annotation.display = true;
-
- notVisibleAnymore.delete(annotation);
- }
- this.visibleAnnotations = visibleNow;
- for(let annotation of notVisibleAnymore){
- annotation.display = false;
- }
- }
- updateMaterialDefaults(pointcloud){
- // PROBLEM STATEMENT:
- // * [min, max] of intensity, source id, etc. are computed as point clouds are loaded
- // * the point cloud material won't know the range it should use until some data is loaded
- // * users can modify the range at runtime, but sensible default ranges should be
- // applied even if no GUI is present
- // * display ranges shouldn't suddenly change even if the actual range changes over time.
- // e.g. the root node has intensity range [1, 478]. One of the descendants increases range to
- // [0, 2047]. We should not automatically change to the new range because that would result
- // in sudden and drastic changes of brightness. We should adjust the min/max of the sidebar slider.
- const material = pointcloud.material;
- const attIntensity = pointcloud.getAttribute("intensity");
-
- if(attIntensity != null && material.intensityRange[0] === Infinity){
- material.intensityRange = [...attIntensity.range];
- }
- // const attIntensity = pointcloud.getAttribute("intensity");
- // if(attIntensity && material.intensityRange[0] === Infinity){
- // material.intensityRange = [...attIntensity.range];
- // }
- // let attributes = pointcloud.getAttributes();
- // for(let attribute of attributes.attributes){
- // if(attribute.range){
- // let range = [...attribute.range];
- // material.computedRange.set(attribute.name, range);
- // //material.setRange(attribute.name, range);
- // }
- // }
- }
- update(delta, timestamp){
- if(Potree.measureTimings) performance.mark("update-start");
- this.dispatchEvent({
- type: 'update_start',
- delta: delta,
- timestamp: timestamp});
-
-
- this.updateScreenSize() //判断是否改变canvas大小
-
-
- const scene = this.scene;
- const camera = scene.getActiveCamera();
- const visiblePointClouds = this.scene.pointclouds.filter(pc => pc.visible)
-
- Potree.pointLoadLimit = Potree.pointBudget * 2;
- const lTarget = camera.position.clone().add(camera.getWorldDirection(new THREE.Vector3()).multiplyScalar(1000));
- this.scene.directionalLight.position.copy(camera.position);
- this.scene.directionalLight.lookAt(lTarget);
-
- for (let pointcloud of visiblePointClouds) {
- pointcloud.showBoundingBox = this.showBoundingBox;
- pointcloud.generateDEM = this.generateDEM;
- pointcloud.minimumNodePixelSize = this.minNodeSize;
- let material = pointcloud.material;
- material.uniforms.uFilterReturnNumberRange.value = this.filterReturnNumberRange;
- material.uniforms.uFilterNumberOfReturnsRange.value = this.filterNumberOfReturnsRange;
- material.uniforms.uFilterGPSTimeClipRange.value = this.filterGPSTimeRange;
- material.uniforms.uFilterPointSourceIDClipRange.value = this.filterPointSourceIDRange;
- material.classification = this.classifications;
- material.recomputeClassification();
- this.updateMaterialDefaults(pointcloud);
- }
- {
- if(this.showBoundingBox){
- let bbRoot = this.scene.scene.getObjectByName("potree_bounding_box_root");
- if(!bbRoot){
- let node = new THREE.Object3D();
- node.name = "potree_bounding_box_root";
- this.scene.scene.add(node);
- bbRoot = node;
- }
- let visibleBoxes = [];
- for(let pointcloud of this.scene.pointclouds){
- for(let node of pointcloud.visibleNodes.filter(vn => vn.boundingBoxNode !== undefined)){
- let box = node.boundingBoxNode;
- visibleBoxes.push(box);
- }
- }
- bbRoot.children = visibleBoxes;
- }
- }
- if (!this.freeze) {
-
- /*let cameraGroup = []
- let size = this.renderer.getSize(new THREE.Vector2())
- if(this.viewports){
- this.viewports.forEach(viewport=>{
- if(!viewport.active)return
- cameraGroup.push({camera:viewport.camera, areaSize:new THREE.Vector2(Math.floor(size.x * viewport.width), Math.floor(size.y * viewport.height))})
- })
- }else{
- cameraGroup.push({camera, areaSize:size})
- }
- let result = Potree.updatePointClouds(scene.pointclouds, cameraGroup );
- */
- // DEBUG - ONLY DISPLAY NODES THAT INTERSECT MOUSE
- //if(false){
- // let renderer = viewer.renderer;
- // let mouse = viewer.inputHandler.mouse;
- // let nmouse = {
- // x: (mouse.x / renderer.domElement.clientWidth) * 2 - 1,
- // y: -(mouse.y / renderer.domElement.clientHeight) * 2 + 1
- // };
- // let pickParams = {};
- // //if(params.pickClipped){
- // // pickParams.pickClipped = params.pickClipped;
- // //}
- // pickParams.x = mouse.x;
- // pickParams.y = renderer.domElement.clientHeight - mouse.y;
- // let raycaster = new THREE.Raycaster();
- // raycaster.setFromCamera(nmouse, camera);
- // let ray = raycaster.ray;
- // for(let pointcloud of scene.pointclouds){
- // let nodes = pointcloud.nodesOnRay(pointcloud.visibleNodes, ray);
- // pointcloud.visibleNodes = nodes;
- // }
- //}
- // const tStart = performance.now();
- // const worldPos = new THREE.Vector3();
- // const camPos = viewer.scene.getActiveCamera().getWorldPosition(new THREE.Vector3());
- // let lowestDistance = Infinity;
- // let numNodes = 0;
- // viewer.scene.scene.traverse(node => {
- // node.getWorldPosition(worldPos);
- // const distance = worldPos.distanceTo(camPos);
- // lowestDistance = Math.min(lowestDistance, distance);
- // numNodes++;
- // if(Number.isNaN(distance)){
- // console.error(":(");
- // }
- // });
- // const duration = (performance.now() - tStart).toFixed(2);
- // Potree.debug.computeNearDuration = duration;
- // Potree.debug.numNodes = numNodes;
- //console.log(lowestDistance.toString(2), duration);
- //搬走
- /* const tStart = performance.now();
- const campos = camera.position;
- let closestImage = Infinity;
- for(const images of this.scene.orientedImages){
- for(const image of images.images){
- const distance = image.mesh.position.distanceTo(campos);
- closestImage = Math.min(closestImage, distance);
- }
- }
- const tEnd = performance.now();
- if(result.lowestSpacing !== Infinity){
- let near = result.lowestSpacing * 10.0;
- let far = -this.getBoundingBox().applyMatrix4(camera.matrixWorldInverse).min.z;
- far = Math.max(far * 1.5, 10000);
- near = Math.min(100.0, Math.max(0.01, near));
- near = Math.min(near, closestImage);
- far = Math.max(far, near + 10000);
- if(near === Infinity){
- near = 0.1;
- }
-
- camera.near = near;
- camera.far = far;
- }else{
- // don't change near and far in this case
- }
- if(this.scene.cameraMode == CameraMode.ORTHOGRAPHIC) {
- camera.near = -camera.far;
- }*/
- }
-
-
-
-
-
-
-
-
-
-
- this.scene.cameraP.fov = this.fov;
-
- let controls = this.getControls();
- if (controls === this.deviceControls) {
- this.controls.setScene(scene);
- this.controls.update(delta);
- this.scene.cameraP.position.copy(scene.view.position);
- this.scene.cameraO.position.copy(scene.view.position);
- } else if (controls !== null) {
- controls.setScene(scene);
- controls.update(delta);
-
- //更新camera
- this.viewports.forEach(viewport=>{
- if(!viewport.active)return
- viewport.view.applyToCamera(viewport.camera)
-
- })
- }
-
- /* this.viewports.forEach(e=>{//判断camera画面是否改变
- if(e.cameraChanged()){
- this.dispatchEvent({
- type: "camera_changed",
- camera: e.camera,
- viewport : e
- })
-
- }
- }) */
-
- this.cameraChanged()//判断camera画面是否改变
-
- /* {//判断camera画面是否改变
- if(this._previousCamera === undefined){
- this._previousCamera = this.scene.getActiveCamera().clone();
- this._previousCamera.rotation.copy(this.scene.getActiveCamera().rotation);
- }
- if(!this._previousCamera.matrixWorld.equals(camera.matrixWorld) ||
- !this._previousCamera.projectionMatrix.equals(camera.projectionMatrix)
- ){
- this.dispatchEvent({
- type: "camera_changed",
- previous: this._previousCamera,
- camera: camera
- });
- }
- this._previousCamera = this.scene.getActiveCamera().clone();
- this._previousCamera.rotation.copy(this.scene.getActiveCamera().rotation);
- } */
-
- { // update clip boxes
- let boxes = [];
-
- // volumes with clipping enabled
- //boxes.push(...this.scene.volumes.filter(v => (v.clip)));
- boxes.push(...this.scene.volumes.filter(v => (v.clip && v instanceof BoxVolume)));
- // profile segments
- for(let profile of this.scene.profiles){
- boxes.push(...profile.boxes);
- }
-
- // Needed for .getInverse(), pre-empt a determinant of 0, see #815 / #816
- let degenerate = (box) => box.matrixWorld.determinant() !== 0;
-
- let clipBoxes = boxes.filter(degenerate).map( box => {
- box.updateMatrixWorld();
-
- let boxInverse = box.matrixWorld.clone().invert();
- let boxPosition = box.getWorldPosition(new THREE.Vector3());
- return {box: box, inverse: boxInverse, position: boxPosition};
- });
- let clipPolygons = this.scene.polygonClipVolumes.filter(vol => vol.initialized);
-
- // set clip volumes in material
- for(let pointcloud of visiblePointClouds){
- pointcloud.material.setClipBoxes(clipBoxes);
- pointcloud.material.setClipPolygons(clipPolygons, this.clippingTool.maxPolygonVertices);
- pointcloud.material.clipTask = this.clipTask;
- pointcloud.material.clipMethod = this.clipMethod;
- }
- }
- {
- for(let pointcloud of visiblePointClouds){
- pointcloud.material.elevationGradientRepeat = this.elevationGradientRepeat;
- }
- }
-
- { // update navigation cube
- this.navigationCube.update(camera.rotation);
- }
- this.updateAnnotations();
-
- if(this.mapView){
- this.mapView.update(delta);
- if(this.mapView.sceneProjection){
- $( "#potree_map_toggle" ).css("display", "block");
-
- }
- }
- TWEEN.update(timestamp);
- transitions.update(delta);
-
-
- this.dispatchEvent({
- type: 'update',
- delta: delta,
- timestamp: timestamp});
-
- if(Potree.measureTimings) {
- performance.mark("update-end");
- performance.measure("update", "update-start", "update-end");
- }
-
-
- //add ------
- this.reticule.updateVisible()
- this.mapViewer.update(delta)
- }
- updateViewPointcloud(camera, areaSize, isViewport){
-
-
- let result = Potree.updatePointClouds(this.scene.pointclouds, camera, areaSize );
-
- //if(isViewport)return
- const tStart = performance.now();
- const campos = camera.position;
- let closestImage = Infinity;
- for(const images of this.scene.orientedImages){
- for(const image of images.images){
- const distance = image.mesh.position.distanceTo(campos);
- closestImage = Math.min(closestImage, distance);
- }
- }
- const tEnd = performance.now();
- //改:不根据点云修改视野near far
- var near = camera.near, far = camera.far
-
- if(!camera.limitFar && result.lowestSpacing !== Infinity){
-
- let near = result.lowestSpacing * 10.0;
- let far = -this.getBoundingBox().applyMatrix4(camera.matrixWorldInverse).min.z;
- far = Math.max(far * 1.5, 10000);
- near = Math.min(100.0, Math.max(0.01, near));
- near = Math.min(near, closestImage);
- far = Math.max(far, near + 10000);
- if(near === Infinity){
- near = 0.1;
- }
-
- camera.near = near;
- camera.far = far;
- }
- if(this.scene.cameraMode == CameraMode.ORTHOGRAPHIC) {//???
- camera.near = -camera.far;
- }
- if(near != camera.near || far != camera.far){
- camera.updateProjectionMatrix()
- }
-
- //注:pointcloud.visibleNodes会随着near far自动更新
- }
-
-
-
- getPRenderer(){
- if(this.useHQ){
- if (!this.hqRenderer) {
- this.hqRenderer = new HQSplatRenderer(this);
- }
- this.hqRenderer.useEDL = this.useEDL;
- return this.hqRenderer;
- }else{
- /* if (this.useEDL && Features.SHADER_EDL.isSupported()) {
- if (!this.edlRenderer) {
- this.edlRenderer = new EDLRenderer(this);
- }
- return this.edlRenderer;
- } else {
- if (!this.potreeRenderer) {
- this.potreeRenderer = new PotreeRenderer(this);
- }
- return this.potreeRenderer;
- } */
-
- if (!this.edlRenderer) {
- this.edlRenderer = new EDLRenderer(this);
- }
- return this.edlRenderer;
-
- }
- }
- renderVR(){
- let renderer = this.renderer;
- renderer.setClearColor(0x550000, 0);
- renderer.clear();
- let xr = renderer.xr;
- let dbg = new THREE.PerspectiveCamera();
- let xrCameras = xr.getCamera(dbg);
- if(xrCameras.cameras.length !== 2){
- return;
- }
- let makeCam = this.vrControls.getCamera.bind(this.vrControls);
- { // clear framebuffer
- if(viewer.background === "skybox"){
- renderer.setClearColor(0xff0000, 1);
- }else if(viewer.background === "gradient"){
- renderer.setClearColor(0x112233, 1);
- }else if(viewer.background === "black"){
- renderer.setClearColor(0x000000, 1);
- }else if(viewer.background === "white"){
- renderer.setClearColor(0xFFFFFF, 1);
- }else{
- renderer.setClearColor(0x000000, 0);
- }
- renderer.clear();
- }
- // render background
- if(this.background === "skybox"){
- let {skybox} = this;
- let cam = makeCam();
- skybox.camera.rotation.copy(cam.rotation);
- skybox.camera.fov = cam.fov;
- skybox.camera.aspect = cam.aspect;
-
- // let dbg = new THREE.Object3D();
- let dbg = skybox.parent;
- // dbg.up.set(0, 0, 1);
- dbg.rotation.x = Math.PI / 2;
- // skybox.camera.parent = dbg;
- // dbg.children.push(skybox.camera);
- dbg.updateMatrix();
- dbg.updateMatrixWorld();
- skybox.camera.updateMatrix();
- skybox.camera.updateMatrixWorld();
- skybox.camera.updateProjectionMatrix();
- renderer.render(skybox.scene, skybox.camera);
- // renderer.render(skybox.scene, cam);
- }else if(this.background === "gradient"){
- // renderer.render(this.scene.sceneBG, this.scene.cameraBG);
- }
- this.renderer.xr.getSession().updateRenderState({
- depthNear: 0.1,
- depthFar: 10000
- });
-
- let cam = null;
- let view = null;
- { // render world scene
- cam = makeCam();
- cam.position.z -= 0.8 * cam.scale.x;
- cam.parent = null;
- // cam.near = 0.05;
- cam.near = viewer.scene.getActiveCamera().near;
- cam.far = viewer.scene.getActiveCamera().far;
- cam.updateMatrix();
- cam.updateMatrixWorld();
- this.scene.scene.updateMatrix();
- this.scene.scene.updateMatrixWorld();
- this.scene.scene.matrixAutoUpdate = false;
- let camWorld = cam.matrixWorld.clone();
- view = camWorld.clone().invert();
- this.scene.scene.matrix.copy(view);
- this.scene.scene.matrixWorld.copy(view);
- cam.matrix.identity();
- cam.matrixWorld.identity();
- cam.matrixWorldInverse.identity();
- renderer.render(this.scene.scene, cam);
- this.scene.scene.matrixWorld.identity();
- }
-
- for(let pointcloud of this.scene.pointclouds){
- let viewport = xrCameras.cameras[0].viewport;
- pointcloud.material.useEDL = false;
- pointcloud.screenHeight = viewport.height;
- pointcloud.screenWidth = viewport.width;
- // automatically switch to paraboloids because they cause far less flickering in VR,
- // when point sizes are larger than around 2 pixels
- // if(Features.SHADER_INTERPOLATION.isSupported()){
- // pointcloud.material.shape = Potree.PointShape.PARABOLOID;
- // }
- }
-
- // render point clouds
- for(let xrCamera of xrCameras.cameras){
- let v = xrCamera.viewport;
- renderer.setViewport(v.x, v.y, v.width, v.height);
- // xrCamera.fov = 90;
- { // estimate VR fov
- let proj = xrCamera.projectionMatrix;
- let inv = proj.clone().invert();
- let p1 = new THREE.Vector4(0, 1, -1, 1).applyMatrix4(inv);
- let rad = p1.y
- let fov = 180 * (rad / Math.PI);
- xrCamera.fov = fov;
- }
- for(let pointcloud of this.scene.pointclouds){
- const {material} = pointcloud;
- material.useEDL = false;
- }
- let vrWorld = view.clone().invert();
- vrWorld.multiply(xrCamera.matrixWorld);
- let vrView = vrWorld.clone().invert();
- this.pRenderer.render(this.scene.scenePointCloud, xrCamera, null, {
- viewOverride: vrView,
- });
- }
- { // render VR scene
- let cam = makeCam();
- cam.parent = null;
- renderer.render(this.sceneVR, cam);
- }
- renderer.resetState();
- }
- clear(params={}){
- let background = params.background || this.background;
- let backgroundOpacity = params.backgroundOpacity == void 0 ? this.backgroundOpacity : params.backgroundOpacity//如果想完全透明,只需要backgroundOpacity为0
- let renderer = this.renderer
- //let gl = renderer.getContext()
-
- if(background instanceof THREE.Color){ //add
- renderer.setClearColor(background, backgroundOpacity);
- }else if(background === "skybox"){
- renderer.setClearColor(0x000000, 0);
- } else if (background === 'gradient') {
- renderer.setClearColor(0x000000, 0);
- } else if (background === 'black') {
- renderer.setClearColor(0x000000, 1);
- } else if (background === 'white') {
- renderer.setClearColor(0xFFFFFF, 1);
- } else {
- renderer.setClearColor(0x000000, 0);
- }
-
- params.target || renderer.clear();
-
-
- }
- renderDefault(params_={}){
- let pRenderer = this.getPRenderer();
- let renderSize
- if(params_.target){
- renderSize = new THREE.Vector2(params_.target.width, params_.target.height)
- if(!params_.viewports){
- console.warn('必须指定target的viewport! 且target大小和viewport.resolution2相同')
- }
- }else{
- renderSize = this.renderer.getSize(new THREE.Vector2());
- }
-
-
- var viewports = params_.viewports || this.viewports
- let needSResize = viewports.filter(e=>e.active).length > 1 || params_.resize
-
-
-
- viewports.forEach(view=>{
- let params = $.extend({},params_);
- //if(!params.target){
- params.camera = params.camera || view.camera;
- params.extraEnableLayers = view.extraEnableLayers
- //}
-
- if(!view.active)return
- var left,bottom,width,height
- {
- left = Math.floor(renderSize.x * view.left)
- bottom = Math.floor(renderSize.y * view.bottom)
-
- /* if(params_.target){//有target时最好viewport是专门建出来的
- width = Math.floor(renderSize.x * view.width)
- height = Math.floor(renderSize.y * view.height)
- }else{ */
- width = view.resolution.x // 用的是client的width和height
- height = view.resolution.y
- //}
- if(width == 0 || height == 0)return
-
- let scissorTest = view.width<1 || view.height<1
- if(params_.target){
- params_.target.viewport.set(left, bottom, width, height);
- scissorTest && params_.target.scissor.set(left, bottom, width, height);
- params_.target.scissorTest = scissorTest
- }else{
- this.renderer.setViewport(left, bottom, width, height) //规定视口,影响图形变换
- scissorTest && this.renderer.setScissor( left, bottom, width, height );//规定渲染范围
- this.renderer.setScissorTest( scissorTest );//开启WebGL剪裁测试功能,如果不开启,.setScissor方法设置的范围不起作用 | width==1且height==1时开启会只有鼠标的地方刷新,很奇怪
-
- }
-
- }
-
- if(needSResize){
- this.emitResizeMsg( { viewport:view} )
- }
-
- //needSResize && this.emitResizeMsg({resolution: params_.target ? new THREE.Vector2(width,height) : view.resolution2, left:view.left, bottom:view.bottom })//resize everything such as lines targets
-
-
-
- viewer.dispatchEvent({type: "render.begin", viewer: viewer, viewport:view, params });
-
- if(view.render){
- view.render({
- target: params_.target, renderer:this.renderer, clear:this.clear.bind(this),
- renderOverlay: this.renderOverlay.bind(this), force:!view.noPointcloud //如果要渲染点云,必须也一直渲染地图,否则地图会被覆盖(点云目前未能获取是否改变,也可能有其他动态物体,所以还是一直渲染的好)
- })
- }
-
-
-
-
- if(!view.noPointcloud ){
-
- //if(!params.target){
- params.width = width; params.height = height;
- //}
- if(view.render){
- params.noBG = true
- }
-
-
-
- view.beforeRender && view.beforeRender(view)
-
- this.updateViewPointcloud(params.camera, new THREE.Vector2(params.width,params.height), true)
-
- params.background = view.background
- params.backgroundColor = view.backgroundColor
- params.backgroundOpacity = view.backgroundOpacity
- view.render || this.clear(params)
- pRenderer.clearTargets(params);
- pRenderer.render(params);
-
-
- this.renderOverlay(params)
- }
-
-
-
- this.dispatchEvent({type: "render.end", viewer: this, viewport:view });
- })
-
- this.renderer.setRenderTarget(null)
-
-
- }
-
-
- renderOverlay(params){
- let camera = params.camera ? params.camera : this.scene.getActiveCamera();
-
-
-
-
- if(!params.magnifier){//为什么要在点云之后渲染,否则透明失效 、 会被点云覆盖
- this.setCameraLayers(camera, ['sceneObjects','marker','reticule','route'], params.extraEnableLayers) //透明贴图层 skybox 、reticule marker 不能遮住测量线
- this.renderer.render(this.scene.scene, camera);
- }
- this.dispatchEvent({type: "render.pass.scene", viewer: viewer});
-
- //清除深度 !!!!
- this.renderer.clearDepth();
- this.transformationTool.update();
-
-
-
- if(!params.magnifier){
- //测量线
- this.dispatchEvent({type: "render.pass.perspective_overlay", camera});
-
- if(!params.screenshot && !params.isMap){
- this.setCameraLayers(camera, ['magnifier']) //magnifier 遮住测量线
- this.renderer.render(this.scene.scene, camera);
- }
- }
-
-
- this.setCameraLayers(camera, ['volume','transformationTool'])
- this.renderer.render(this.clippingTool.sceneVolume, camera);
- this.renderer.render(this.transformationTool.scene, camera);
-
-
- }
-
-
-
-
- setCameraLayers(camera, enableLayers, extraEnableLayers=[]){//add
- camera.layers.disableAll()
- enableLayers.concat(extraEnableLayers).forEach(e=>{
- let layer = Potree.config.renderLayers[e]
- if(layer == void 0){
- console.error('setCameraLayer没找到layer!');
- return
- }
- camera.layers.enable(layer)
- })
- }
- setObjectLayers(object, layerName){//add
- let layer = Potree.config.renderLayers[layerName]
- if(layer == void 0){
- console.error('setCameraLayer没找到layer!');
- return
- }
- object.traverse(e=>{
- e.layers.set(layer)
- })
- }
-
-
- updateVisible(object, reason, ifShow){//当所有加入的条件都不为false时才显示. reason='force'一般是强制、临时的
- if(!object.unvisibleReasons) object.unvisibleReasons = []; //如果length>0代表不可见
-
-
- if(ifShow){
- var index = object.unvisibleReasons.indexOf(reason)
- index > -1 && object.unvisibleReasons.splice(index, 1)
- if(object.unvisibleReasons.length == 0){
- object.visible = true;
- object.dispatchEvent({
- type: 'isVisible',
- visible:true
- })
- }
- }else{
- var visiBefore = object.visible
- if(!object.unvisibleReasons.includes(reason)) object.unvisibleReasons.push(reason)
- object.visible = false
- visiBefore && object.dispatchEvent({
- type: 'isVisible',
- visible:false,
- reason,
- })
- }
-
- }
-
- getObjVisiByReason(object,reason){//获取在某条件下是否可见. 注: 用户在数据集选择可不可见为"datasetSelection"
- if(object.visible)return true
- else{
- return !object.unvisibleReasons || !object.unvisibleReasons.includes(reason)
- }
- }
-
-
-
-
-
-
-
-
- render(params){//add params
- if(Potree.measureTimings) performance.mark("render-start");
- //try{
- const vrActive = this.renderer.xr.isPresenting;
- if(vrActive){
- this.renderVR();
- }else{
- this.renderDefault(params);
- }
- /* }catch(e){
- this.onCrash(e);
- } */
-
- if(Potree.measureTimings){
- performance.mark("render-end");
- performance.measure("render", "render-start", "render-end");
- }
- }
- startScreenshot(info={}, width=800, height=400, compressRatio){//add
-
-
- //抗锯齿待加 1 post处理 2截图大张再抗锯齿缩小
-
-
-
- let deferred = $.Deferred();
-
- var screenshot = ()=>{
- var { buffer } = this.makeScreenshot( new THREE.Vector2(width,height) );
-
- var dataUrl = Potree.Utils.pixelsArrayToDataUrl(buffer, width, height, compressRatio)
-
- if(!Potree.settings.isOfficial){
- Common.downloadFile(dataUrl, 'screenshot.jpg')
- }
- deferred.resolve(dataUrl)
-
-
-
- {//恢复:
-
- if(info.type == 'measure'){
- this.scene.measurements.forEach(e=>this.updateVisible(e, 'screenshot',true))
- }
- this.images360.panos.forEach(pano=>{
- viewer.updateVisible(pano, 'screenshot', true)
- })
- viewer.updateVisible(this.reticule, 'screenshot', true)
- viewer.updateVisible(this.mapViewer.cursor, 'screenshot', true)
-
- if(oldStates.attachedToViewer != this.mapViewer.attachedToViewer){
- if(info.type == 'measure'){
- this.mapViewer.attachToMainViewer(false)
- }
- }
- mapViewport.camera.zoom = oldStates.mapZoom
-
-
-
- oldStates.viewports.forEach(old=>{//恢复相机
- var viewport = [mapViewport, mainViewport].find(v=>v.name == old.name);
- viewport.left = old.left;
- viewport.width = old.width;
- viewport.view.copy(old.view)
- viewport.view.applyToCamera(viewport.camera);
-
- })
-
- viewer.updateScreenSize({forceUpdateSize:true})//更新像素
-
- oldStates.viewports.forEach(old=>{//恢复相机
- var viewport = [mapViewport, mainViewport].find(v=>v.name == old.name);
- this.dispatchEvent({ //update map
- type: "camera_changed",
- camera: viewport.camera,
- viewport : viewport
- })
- })
- }
- }
-
- let mapViewport = this.mapViewer.viewports[0]
- let mainViewport = this.mainViewport
- let oldStates = {
- attachedToViewer : this.mapViewer.attachedToViewer,
- viewports : [mapViewport, mainViewport].map(e=>{
- return e.clone()
- }),
- mapZoom: mapViewport.camera.zoom
- }
- //令漫游点不可见
- this.images360.panos.forEach(pano=>{
- viewer.updateVisible(pano, 'screenshot', false)
- })
- //令reticule不可见
- viewer.updateVisible(this.reticule, 'screenshot', false)
- //令mapCursor不可见
- viewer.updateVisible(this.mapViewer.cursor, 'screenshot', false)
-
-
- if(info.type == 'measure'){//要截图双屏
- this.scene.measurements.forEach(e=>this.updateVisible(e,'screenshot',e == info.measurement) )
-
-
- this.mapViewer.attachToMainViewer(true, 'measure', 0.5)
-
- viewer.updateScreenSize({forceUpdateSize:true, width, height}) //更新viewports相机透视
-
- //不同角度截图 得到三维的会不一样,因为focusOnObject是根据方向的
- let promise = this.focusOnObject(info.measurement, 'measure', 0, /* {mapDont:true} */)
- promise.done(()=>{
-
- this.viewports.forEach(e=>{
- e.view.applyToCamera(e.camera)
-
- this.dispatchEvent({ //update map
- type: "camera_changed",
- camera: e.camera,
- viewport : e
- })
-
- })
-
- this.mapViewer.waitLoadDone(screenshot.bind(this))//等待地图所有加载完
-
- })
-
- }else{
- screenshot()
- }
-
-
-
-
- return deferred.promise()
-
-
- }
-
-
- focusOnObject(object, type, duration, o={} ) {
- //飞向热点、测量线等 。
- let deferred = $.Deferred();
- let target = new THREE.Vector3,
- position = new THREE.Vector3,
- dis;
- duration = duration == void 0 ? 2000 : duration;
- let camera = viewer.scene.getActiveCamera()
-
- if (type == 'measure') {
- let bound = new THREE.Box3()
- object.points.forEach(p => bound.expandByPoint(p))
-
- let boundSize = bound.getSize(new THREE.Vector3)
- let {center,radius} = bound.getBoundingSphere({center:new THREE.Vector3}) //用不box的算不准,就保守用sphere了,缺点是无法占满屏,优点是不会靠太近
- target.copy(object.getCenter())//copy(center)
-
- let aspect = 1
-
- if(camera.aspect > aspect){//视野更宽则用bound的纵向来决定
- dis = radius/ THREE.Math.degToRad(camera.fov / 2)
- }else{
- let hfov = cameraLight.getHFOVForCamera(camera, camera.aspect, 1 );
- dis = radius / THREE.Math.degToRad(hfov / 2)
- }
-
- if(o.mapDont || this.mapViewer.attachedToViewer){
- this.mapViewer.fitToBound(target.clone(), boundSize.clone().multiplyScalar(2), duration)
- }
-
-
- if(Potree.settings.displayMode == 'showPointCloud'){
- let dir = new THREE.Vector3().subVectors(camera.position, target).normalize()
- position.copy(target).add(dir.multiplyScalar(dis))
-
- }else if(Potree.settings.displayMode == 'showPanos'){
- let pano = viewer.images360.fitPanoTowardPoint({
- point : target,
- bestDistance : dis * 0.5 //乘以小数是为了尽量靠近
- })
- pano && viewer.images360.flyToPano({pano, target, duration, deferred })
- return deferred
- }
- } else if (type == 'tag') {
- const bestDistance = 2
- target.copy(object.position)
- if(Potree.settings.displayMode == 'showPointCloud'){
- dis = bestDistance
- let dir = new THREE.Vector3().subVectors(camera.position, target).normalize()
- position.copy(target).add(dir.multiplyScalar(dis))
-
- }else if(Potree.settings.displayMode == 'showPanos'){
- let pano = viewer.images360.fitPanoTowardPoint({
- point : target,
- bestDistance //越近越好,但不要太近,bestDistance左右差不多
- })
- pano && viewer.images360.flyToPano({pano, target, duration, deferred })
- return deferred
- }
-
- }
- viewer.scene.view.setView(position, target, duration, ()=>{
- deferred.resolve()
- })
-
-
-
- return deferred.promise()
- }
-
- resolveTimings(timestamp){
- if(Potree.measureTimings){
- if(!this.toggle){
- this.toggle = timestamp;
- }
- let duration = timestamp - this.toggle;
- if(duration > 1000.0){
-
- let measures = performance.getEntriesByType("measure");
-
- let names = new Set();
- for(let measure of measures){
- names.add(measure.name);
- }
-
- let groups = new Map();
- for(let name of names){
- groups.set(name, {
- measures: [],
- sum: 0,
- n: 0,
- min: Infinity,
- max: -Infinity
- });
- }
-
- for(let measure of measures){
- let group = groups.get(measure.name);
- group.measures.push(measure);
- group.sum += measure.duration;
- group.n++;
- group.min = Math.min(group.min, measure.duration);
- group.max = Math.max(group.max, measure.duration);
- }
- let glQueries = Potree.resolveQueries(this.renderer.getContext());
- for(let [key, value] of glQueries){
- let group = {
- measures: value.map(v => {return {duration: v}}),
- sum: value.reduce( (a, i) => a + i, 0),
- n: value.length,
- min: Math.min(...value),
- max: Math.max(...value)
- };
- let groupname = `[tq] ${key}`;
- groups.set(groupname, group);
- names.add(groupname);
- }
-
- for(let [name, group] of groups){
- group.mean = group.sum / group.n;
- group.measures.sort( (a, b) => a.duration - b.duration );
-
- if(group.n === 1){
- group.median = group.measures[0].duration;
- }else if(group.n > 1){
- group.median = group.measures[parseInt(group.n / 2)].duration;
- }
-
- }
-
- let cn = Array.from(names).reduce( (a, i) => Math.max(a, i.length), 0) + 5;
- let cmin = 10;
- let cmed = 10;
- let cmax = 10;
- let csam = 6;
-
- let message = ` ${"NAME".padEnd(cn)} |`
- + ` ${"MIN".padStart(cmin)} |`
- + ` ${"MEDIAN".padStart(cmed)} |`
- + ` ${"MAX".padStart(cmax)} |`
- + ` ${"SAMPLES".padStart(csam)} \n`;
- message += ` ${"-".repeat(message.length) }\n`;
-
- names = Array.from(names).sort();
- for(let name of names){
- let group = groups.get(name);
- let min = group.min.toFixed(3);
- let median = group.median.toFixed(3);
- let max = group.max.toFixed(3);
- let n = group.n;
-
- message += ` ${name.padEnd(cn)} |`
- + ` ${min.padStart(cmin)} |`
- + ` ${median.padStart(cmed)} |`
- + ` ${max.padStart(cmax)} |`
- + ` ${n.toString().padStart(csam)}\n`;
- }
- message += `\n`;
- console.log(message);
-
- performance.clearMarks();
- performance.clearMeasures();
- this.toggle = timestamp;
- }
- }
- }
- loop(timestamp){
- if(this.stats){
- this.stats.begin();
- }
- if(Potree.measureTimings){
- performance.mark("loop-start");
- }
- this.update(this.clock.getDelta(), timestamp);
- this.magnifier.render();
- this.render();
-
-
-
- // let vrActive = viewer.renderer.xr.isPresenting;
- // if(vrActive){
- // this.update(this.clock.getDelta(), timestamp);
- // this.render();
- // }else{
- // this.update(this.clock.getDelta(), timestamp);
- // this.render();
- // }
- if(Potree.measureTimings){
- performance.mark("loop-end");
- performance.measure("loop", "loop-start", "loop-end");
- }
-
- this.resolveTimings(timestamp);
- Potree.framenumber++;
- if(this.stats){
- this.stats.end();
- }
- }
- postError(content, params = {}){
- let message = this.postMessage(content, params);
- message.element.addClass("potree_message_error");
- return message;
- }
- postMessage(content, params = {}){
- let message = new Message(content);
- let animationDuration = 100;
- message.element.css("display", "none");
- message.elClose.click( () => {
- message.element.slideToggle(animationDuration);
- let index = this.messages.indexOf(message);
- if(index >= 0){
- this.messages.splice(index, 1);
- }
- });
- this.elMessages.prepend(message.element);
- message.element.slideToggle(animationDuration);
- this.messages.push(message);
- if(params.duration !== undefined){
- let fadeDuration = 500;
- let slideOutDuration = 200;
- setTimeout(() => {
- message.element.animate({
- opacity: 0
- }, fadeDuration);
- message.element.slideToggle(slideOutDuration);
- }, params.duration)
- }
- return message;
- }
-
-
-
-
-
- getBoundingBox (pointclouds) {
- //可以直接返回viewer.bound
- if(!this.bound){
- this.updateModelBound()
- }
- return this.bound.boundingBox.clone()//this.scene.getBoundingBox(pointclouds);
- };
- updateModelBound(){
- this.bound = Utils.computePointcloudsBound(this.scene.pointclouds)
- viewer.farWhenShowPano = this.bound.boundSize.length() * 2//全景漫游时要能看到整个skybox
- }
-
- waitForLoad(object, isLoadedCallback){//等待加载时显示loading。主要是贴图
- this.waitQueue.push({
- object,
- isLoadedCallback,
- })
- 1 === this.waitQueue.length && this.emit("loading", true)
- }
- ifAllLoaded(object){
- if(this.waitQueue.length>0){
- this.waitQueue = this.waitQueue.filter(function(e) {
- return !e.isLoadedCallback()
- })
- }
-
- 0 === this.waitQueue.length && this.emit("loading", false)
- }
-
-
- setView(o={}){
- let callback = ()=>{
- if(o.displayMode){
- Potree.settings.displayMode = o.displayMode
- }
- o.callback && o.callback()
- }
-
- if(o.pano != void 0){//pano 权重高于 position
- this.images360.flyToPano(o)
- }else{
- this.scene.view.setView(o.position, o.target, o.duration, callback)
- }
-
-
- }
- };
- /* t.prototype.getTransformationMatrix = function(t) {//点云截取 所有点在乘上这个矩阵后, 还能落在 1 * 1 * 1的box内的点就是所裁剪的
- var e = this.ViewService.mainView.getVolumeClippingLayer().getBoxFrame()
- , n = (new o.Matrix4).getInverse(e.matrixWorld)
- , i = t.m2w_;
- return (new o.Matrix4).multiplyMatrices(n, i).transpose() */
|