123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- import * as THREE from "../libs/three.js/build/three.module.js";
- import {ClipTask, ClipMethod} from "./defines.js";
- import {Box3Helper} from "./utils/Box3Helper.js";
- export function updatePointClouds(pointclouds,camera, areaSize /* renderer */){
-
- for (let pointcloud of pointclouds) {
- let start = performance.now();
- for (let profileRequest of pointcloud.profileRequests) {
- profileRequest.update();
- let duration = performance.now() - start;
- if(duration > 5){
- break;
- }
- }
- let duration = performance.now() - start;
- }
-
-
- let result = updateVisibility(pointclouds, camera, areaSize );
- for (let pointcloud of pointclouds) {
- //pointcloud.updateMaterial(pointcloud.material, pointcloud.visibleNodes, camera, renderer);//转移到渲染时
- pointcloud.updateVisibleBounds();
- }
- exports.lru.freeMemory();
- return result;
- };
- export function updateVisibilityStructures(pointclouds, camera, areaSize) {
- let frustums = [];
- let camObjPositions = [];
- let priorityQueue = new BinaryHeap(function (x) { return 1 / x.weight; });
- for (let i = 0; i < pointclouds.length; i++) {
- let pointcloud = pointclouds[i];
- if (!pointcloud.initialized()) {
- continue;
- }
- pointcloud.numVisibleNodes = 0;
- pointcloud.numVisiblePoints = 0;
- pointcloud.deepestVisibleLevel = 0;
- pointcloud.visibleNodes = [];
- pointcloud.visibleGeometry = [];
- // frustum in object space
- camera.updateMatrixWorld();
- let frustum = new THREE.Frustum();
- let viewI = camera.matrixWorldInverse;
- let world = pointcloud.matrixWorld;
-
- // use close near plane for frustum intersection
- let frustumCam = camera.clone();
- frustumCam.near = Math.min(camera.near, 0.1);
- frustumCam.updateProjectionMatrix();
- let proj = camera.projectionMatrix;
- let fm = new THREE.Matrix4().multiply(proj).multiply(viewI).multiply(world);
- frustum.setFromProjectionMatrix(fm);
- frustums.push(frustum);
- // camera position in object space
- let view = camera.matrixWorld;
- let worldI = world.clone().invert();
- let camMatrixObject = new THREE.Matrix4().multiply(worldI).multiply(view);
- let camObjPos = new THREE.Vector3().setFromMatrixPosition(camMatrixObject);
- camObjPositions.push(camObjPos);
- if ( viewer.getObjVisiByReason(pointcloud, 'datasetSelection') && pointcloud.root !== null) {//改 visible ->
- priorityQueue.push({pointcloud: i, node: pointcloud.root, weight: Number.MAX_VALUE});
- }
- // hide all previously visible nodes
- // if(pointcloud.root instanceof PointCloudOctreeNode){
- // pointcloud.hideDescendants(pointcloud.root.sceneNode);
- // }
- if (pointcloud.root.isTreeNode()) {
- pointcloud.hideDescendants(pointcloud.root.sceneNode);
- }
- for (let j = 0; j < pointcloud.boundingBoxNodes.length; j++) {
- pointcloud.boundingBoxNodes[j].visible = false;
- }
- }
- return {
- 'frustums': frustums,
- 'camObjPositions': camObjPositions,
- 'priorityQueue': priorityQueue
- };
- };
- export function updateVisibility(pointclouds, camera, areaSize){
- let numVisibleNodes = 0;
- let numVisiblePoints = 0;
- let numVisiblePointsInPointclouds = new Map(pointclouds.map(pc => [pc, 0]));
- let visibleNodes = [];
- let visibleGeometry = [];
- let unloadedGeometry = [];
- let lowestSpacing = Infinity;
- // calculate object space frustum and cam pos and setup priority queue
- let s = updateVisibilityStructures(pointclouds, camera, areaSize);//得到相机可见范围
- let frustums = s.frustums;
- let camObjPositions = s.camObjPositions;
- let priorityQueue = s.priorityQueue;
- let loadedToGPUThisFrame = 0;
-
- let domWidth = areaSize.x; //renderer.domElement.clientWidth;
- let domHeight = areaSize.y;//renderer.domElement.clientHeight;
- // check if pointcloud has been transformed
- // some code will only be executed if changes have been detected
- if(!Potree._pointcloudTransformVersion){
- Potree._pointcloudTransformVersion = new Map();
- }
- let pointcloudTransformVersion = Potree._pointcloudTransformVersion;
- for(let pointcloud of pointclouds){
- if(!viewer.getObjVisiByReason(pointcloud, 'datasetSelection')){//改 visible ->
- continue;
- }
- pointcloud.updateMatrixWorld();
- if(!pointcloudTransformVersion.has(pointcloud)){
- pointcloudTransformVersion.set(pointcloud, {number: 0, transform: pointcloud.matrixWorld.clone()});
- }else{
- let version = pointcloudTransformVersion.get(pointcloud);
- if(!version.transform.equals(pointcloud.matrixWorld)){
- version.number++;
- version.transform.copy(pointcloud.matrixWorld);
- pointcloud.dispatchEvent({
- type: "transformation_changed",
- target: pointcloud
- });
- }
- }
- }
- while (priorityQueue.size() > 0) {
- let element = priorityQueue.pop();
- let node = element.node;
- let parent = element.parent;
- let pointcloud = pointclouds[element.pointcloud];
- // { // restrict to certain nodes for debugging
- // let allowedNodes = ["r", "r0", "r4"];
- // if(!allowedNodes.includes(node.name)){
- // continue;
- // }
- // }
- let box = node.getBoundingBox();
- let frustum = frustums[element.pointcloud];
- let camObjPos = camObjPositions[element.pointcloud];
- let insideFrustum = frustum.intersectsBox(box);
- let maxLevel = pointcloud.maxLevel == void 0 ? Infinity : pointcloud.maxLevel;
- let level = node.getLevel();
- let visible = insideFrustum;
- visible = visible && !(numVisiblePoints + node.getNumPoints() > Potree.pointBudget);
- visible = visible && !(numVisiblePointsInPointclouds.get(pointcloud) + node.getNumPoints() > pointcloud.pointBudget);
- visible = visible && level <= maxLevel; //< 改为 <=
- //visible = visible || node.getLevel() <= 2;
- let clipBoxes = pointcloud.material.clipBoxes;
- if(true && clipBoxes.length > 0){
- //node.debug = false;
- let numIntersecting = 0;
- let numIntersectionVolumes = 0;
- //if(node.name === "r60"){
- // var a = 10;
- //}
- for(let clipBox of clipBoxes){
- let pcWorldInverse = pointcloud.matrixWorld.clone().invert();
- let toPCObject = pcWorldInverse.multiply(clipBox.box.matrixWorld);
- let px = new THREE.Vector3(+0.5, 0, 0).applyMatrix4(pcWorldInverse);
- let nx = new THREE.Vector3(-0.5, 0, 0).applyMatrix4(pcWorldInverse);
- let py = new THREE.Vector3(0, +0.5, 0).applyMatrix4(pcWorldInverse);
- let ny = new THREE.Vector3(0, -0.5, 0).applyMatrix4(pcWorldInverse);
- let pz = new THREE.Vector3(0, 0, +0.5).applyMatrix4(pcWorldInverse);
- let nz = new THREE.Vector3(0, 0, -0.5).applyMatrix4(pcWorldInverse);
- let pxN = new THREE.Vector3().subVectors(nx, px).normalize();
- let nxN = pxN.clone().multiplyScalar(-1);
- let pyN = new THREE.Vector3().subVectors(ny, py).normalize();
- let nyN = pyN.clone().multiplyScalar(-1);
- let pzN = new THREE.Vector3().subVectors(nz, pz).normalize();
- let nzN = pzN.clone().multiplyScalar(-1);
- let pxPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(pxN, px);
- let nxPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(nxN, nx);
- let pyPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(pyN, py);
- let nyPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(nyN, ny);
- let pzPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(pzN, pz);
- let nzPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(nzN, nz);
- //if(window.debugdraw !== undefined && window.debugdraw === true && node.name === "r60"){
- // Potree.utils.debugPlane(viewer.scene.scene, pxPlane, 1, 0xFF0000);
- // Potree.utils.debugPlane(viewer.scene.scene, nxPlane, 1, 0x990000);
- // Potree.utils.debugPlane(viewer.scene.scene, pyPlane, 1, 0x00FF00);
- // Potree.utils.debugPlane(viewer.scene.scene, nyPlane, 1, 0x009900);
- // Potree.utils.debugPlane(viewer.scene.scene, pzPlane, 1, 0x0000FF);
- // Potree.utils.debugPlane(viewer.scene.scene, nzPlane, 1, 0x000099);
- // Potree.utils.debugBox(viewer.scene.scene, box, new THREE.Matrix4(), 0x00FF00);
- // Potree.utils.debugBox(viewer.scene.scene, box, pointcloud.matrixWorld, 0xFF0000);
- // Potree.utils.debugBox(viewer.scene.scene, clipBox.box.boundingBox, clipBox.box.matrixWorld, 0xFF0000);
- // window.debugdraw = false;
- //}
- let frustum = new THREE.Frustum(pxPlane, nxPlane, pyPlane, nyPlane, pzPlane, nzPlane);
- let intersects = frustum.intersectsBox(box);
- if(intersects){
- numIntersecting++;
- }
- numIntersectionVolumes++;
- }
- let insideAny = numIntersecting > 0;
- let insideAll = numIntersecting === numIntersectionVolumes;
- if(pointcloud.material.clipTask === ClipTask.SHOW_INSIDE){
- if(pointcloud.material.clipMethod === ClipMethod.INSIDE_ANY && insideAny){
- //node.debug = true
- }else if(pointcloud.material.clipMethod === ClipMethod.INSIDE_ALL && insideAll){
- //node.debug = true;
- }else{
- visible = false;
- }
- } else if(pointcloud.material.clipTask === ClipTask.SHOW_OUTSIDE){
- //if(pointcloud.material.clipMethod === ClipMethod.INSIDE_ANY && !insideAny){
- // //visible = true;
- // let a = 10;
- //}else if(pointcloud.material.clipMethod === ClipMethod.INSIDE_ALL && !insideAll){
- // //visible = true;
- // let a = 20;
- //}else{
- // visible = false;
- //}
- }
-
- }
- // visible = ["r", "r0", "r06", "r060"].includes(node.name);
- // visible = ["r"].includes(node.name);
- if (node.spacing) {
- lowestSpacing = Math.min(lowestSpacing, node.spacing);
- } else if (node.geometryNode && node.geometryNode.spacing) {
- lowestSpacing = Math.min(lowestSpacing, node.geometryNode.spacing);
- }
- if (numVisiblePoints + node.getNumPoints() > Potree.pointBudget) {
- break;
- }
- if (!visible) {
- continue;
- }
- // TODO: not used, same as the declaration?
- // numVisibleNodes++;
- numVisiblePoints += node.getNumPoints();
- let numVisiblePointsInPointcloud = numVisiblePointsInPointclouds.get(pointcloud);
- numVisiblePointsInPointclouds.set(pointcloud, numVisiblePointsInPointcloud + node.getNumPoints());
- pointcloud.numVisibleNodes++;
- pointcloud.numVisiblePoints += node.getNumPoints();
- if (node.isGeometryNode() && (!parent || parent.isTreeNode())) {
- if (node.isLoaded() && loadedToGPUThisFrame < 2) {
- node = pointcloud.toTreeNode(node, parent);
- loadedToGPUThisFrame++;
- } else {
- unloadedGeometry.push(node);
- visibleGeometry.push(node);
- }
- }
- if (node.isTreeNode()) {
- exports.lru.touch(node.geometryNode);
- node.sceneNode.visible = true;
- node.sceneNode.material = pointcloud.material;
- visibleNodes.push(node);
- pointcloud.visibleNodes.push(node);
- if(node._transformVersion === undefined){
- node._transformVersion = -1;
- }
- let transformVersion = pointcloudTransformVersion.get(pointcloud);
- if(node._transformVersion !== transformVersion.number){
- node.sceneNode.updateMatrix();
- node.sceneNode.matrixWorld.multiplyMatrices(pointcloud.matrixWorld, node.sceneNode.matrix);
- node._transformVersion = transformVersion.number;
- }
- if (pointcloud.showBoundingBox && !node.boundingBoxNode && node.getBoundingBox) {
- let boxHelper = new Box3Helper(node.getBoundingBox());
- boxHelper.matrixAutoUpdate = false;
- pointcloud.boundingBoxNodes.push(boxHelper);
- node.boundingBoxNode = boxHelper;
- node.boundingBoxNode.matrix.copy(pointcloud.matrixWorld);
- } else if (pointcloud.showBoundingBox) {
- node.boundingBoxNode.visible = true;
- node.boundingBoxNode.matrix.copy(pointcloud.matrixWorld);
- } else if (!pointcloud.showBoundingBox && node.boundingBoxNode) {
- node.boundingBoxNode.visible = false;
- }
- // if(node.boundingBoxNode !== undefined && exports.debug.allowedNodes !== undefined){
- // if(!exports.debug.allowedNodes.includes(node.name)){
- // node.boundingBoxNode.visible = false;
- // }
- // }
- }
- // add child nodes to priorityQueue
- let children = node.getChildren();
- for (let i = 0; i < children.length; i++) {
- let child = children[i];
- let weight = 0;
- if(camera.isPerspectiveCamera){
- let sphere = child.getBoundingSphere();
- let center = sphere.center;
- //let distance = sphere.center.distanceTo(camObjPos);
-
- let dx = camObjPos.x - center.x;
- let dy = camObjPos.y - center.y;
- let dz = camObjPos.z - center.z;
-
- let dd = dx * dx + dy * dy + dz * dz;
- let distance = Math.sqrt(dd);
-
-
- let radius = sphere.radius;
-
- let fov = (camera.fov * Math.PI) / 180;
- let slope = Math.tan(fov / 2);
- let projFactor = (0.5 * domHeight) / (slope * distance);
- let screenPixelRadius = radius * projFactor;
-
- if(screenPixelRadius < pointcloud.minimumNodePixelSize){
- continue;
- }
-
- weight = screenPixelRadius;
- if(distance - radius < 0){
- weight = Number.MAX_VALUE;
- }
- } else {
- // TODO ortho visibility
- let bb = child.getBoundingBox();
- let distance = child.getBoundingSphere().center.distanceTo(camObjPos);
- let diagonal = bb.max.clone().sub(bb.min).length();
- //weight = diagonal / distance;
- weight = diagonal;
- }
- priorityQueue.push({pointcloud: element.pointcloud, node: child, parent: node, weight: weight});
- }
- }// end priority queue loop
- { // update DEM
- let maxDEMLevel = 4;
- let candidates = pointclouds.filter(p => (p.generateDEM && p.dem instanceof Potree.DEM));
- for (let pointcloud of candidates) {
- let updatingNodes = pointcloud.visibleNodes.filter(n => n.getLevel() <= maxDEMLevel);
- pointcloud.dem.update(updatingNodes);
- }
- }
- for (let i = 0; i < Math.min(Potree.maxNodesLoading, unloadedGeometry.length); i++) {
- unloadedGeometry[i].load();
- }
- return {
- visibleNodes: visibleNodes,
- numVisiblePoints: numVisiblePoints,
- lowestSpacing: lowestSpacing
- };
- };
- //console
- //viewer.scene.pointclouds[0].visibleNodes.map(e=> e && e.name )
- //viewer.scene.pointclouds[0].visibleNodes.map(e=>e.children.map(e=>e && e.name))
|