xzw 2 سال پیش
والد
کامیت
16765d2c5d

+ 6 - 2
src/Potree.js

@@ -34,7 +34,7 @@ export * from "./materials/NormalizationEDLMaterial.js";
 export * from "./materials/NormalizationMaterial.js";
 export * from "./materials/ExtendPointCloudMaterial.js";
 
-export * from "./loader/POCLoader.js";
+export * from "./loader/POCLoaderNew.js";
 export * from "./modules/loader/2.0/OctreeLoader.js";
 export * from "./loader/EptLoader.js";
 export * from "./loader/ept/BinaryLoader.js";
@@ -61,6 +61,10 @@ export * from "./utils/PointCloudSM.js";
 												// export * from "./objects/tool/Volume.js";
 												// export * from "./objects/tool/VolumeTool.js";
 												// export * from "./objects/tool/Compass.js";
+                                                
+                                                
+export * from "./custom/objects/tool/Measure.js";
+export * from "./custom/objects/tool/MeasuringTool.js";
 export * from "./utils/PolygonClipVolume.js";
 export * from "./utils/Profile.js";
 export * from "./utils/ProfileTool.js";
@@ -90,7 +94,7 @@ import "./extensions/Ray.js";
 
 import {LRU} from "./LRU.js";
 import {OctreeLoader} from "./modules/loader/2.0/OctreeLoader.js";
-import {POCLoader} from "./loader/POCLoader.js";
+import {POCLoader} from "./loader/POCLoaderNew.js";
 import {EptLoader} from "./loader/EptLoader.js";
 import {ExtendPointCloudOctree} from "./ExtendPointCloudOctree.js"; 
 import {WorkerPool} from "./WorkerPool.js";

+ 0 - 106
src/custom/ExtendEventDispatcher.js

@@ -1,106 +0,0 @@
-import * as THREE from "../../libs/three.js/build/three.module.js";
-
-export class ExtendEventDispatcher extends THREE.EventDispatcher {
-	constructor () {
-		super();
-	}
-
-    addEventListener(type, listener, importance=0){    //add importance
-        if ( this._listeners === undefined ) this._listeners = {};
-    
-            const listeners = this._listeners;
-    
-            if ( listeners[ type ] === undefined ) {
-    
-                listeners[ type ] = [];
-    
-            }
-    
-            if ( !listeners[ type ].some(e=>e.listener == listener )  ) { 
-                //listeners[ type ].push( listener );
-                listeners[type].push({ listener,  importance});
-                listeners[type] = listeners[type].sort((e,a)=> a.importance - e.importance)//add
-            }
-    }
-    
-    hasEventListener(type, listener){
-        if ( this._listeners === undefined ) return false;
-    
-        const listeners = this._listeners;
-    
-        return listeners[ type ] !== undefined &&  listeners[ type ].some(e=>e.listener == listener )  
-    }
-    
-    removeEventListener(type, listener){
-        if ( this._listeners === undefined ) return;
-    
-        const listeners = this._listeners;
-        const listenerArray = listeners[ type ];
-    
-        if ( listenerArray !== undefined ) {
-    
-            /* const index = listenerArray.indexOf( listener );
-    
-            if ( index !== - 1 ) {
-    
-                listenerArray.splice( index, 1 );
-    
-            } */
-    
-            let item = listenerArray.find(e=>e.listener == listener)
-            item && listenerArray.splice(listenerArray.indexOf(item), 1);
-    
-        }
-    }
-    
-    removeEventListeners(type){  //add
-        if(this._listeners && this._listeners[type] !== undefined){
-            delete this._listeners[type];
-        }
-    }
-    
-    removeAllListeners(){  //add
-        this._listeners = {};
-    }
-    
-    dispatchEvent(event){ 
-        if(typeof event == 'string'){//add
-                event = {type:event}
-            }
-            if ( this._listeners === undefined ) return;
-    
-            const listeners = this._listeners;
-            const listenerArray = listeners[ event.type ];
-    
-            if ( listenerArray !== undefined ) {
-    
-                event.target = this;
-    
-                // Make a copy, in case listeners are removed while iterating.
-                 
-                for(let {listener} of listenerArray.slice(0)){
-                    let result = listener.call(this, event);   //add stopContinue
-                    if(result && result.stopContinue){
-                        break
-                    }
-                }
-    
-            }
-    }
-    
-    traverse(callback){ 
-            let result = callback( this );
-            if(result && result.stopContinue){//xzw add
-                return 
-            }
-                 
-            const children = this.children;
-    
-            for ( let i = 0, l = children.length; i < l; i ++ ) {
-    
-                children[ i ].traverse( callback );
-    
-            }
-    }
-    
-};

+ 2 - 2
src/materials/BasicMaterial.js

@@ -1,6 +1,6 @@
 
-import * as THREE from "../../libs/three.js/build/three.module.js";
-import {Shaders} from "../../build/shaders/shaders.js";
+import * as THREE from "../../../libs/three.js/build/three.module.js";
+import {Shaders} from "../../../build/shaders/shaders.js";
  
 
 class BasicMaterial  extends THREE.ShaderMaterial{ 

+ 1 - 1
src/materials/postprocessing/CopyShader.js

@@ -3,7 +3,7 @@
  *
  * Full-screen textured quad shader
  */
-import * as THREE from "../../../libs/three.js/build/three.module.js";
+import * as THREE from "../../../../libs/three.js/build/three.module.js";
 
 
 

+ 1 - 1
src/materials/postprocessing/EffectComposer.js

@@ -1,7 +1,7 @@
 /**
  * @author alteredq / http://alteredqualia.com/
  */
-import * as THREE from "../../../libs/three.js/build/three.module.js";
+import * as THREE from "../../../../libs/three.js/build/three.module.js";
 import CopyShader from './CopyShader'
 import {ShaderPass} from './ShaderPass' 
 import { MaskPass, ClearMaskPass } from './MaskPass.js'; 

+ 1 - 1
src/materials/postprocessing/FXAAShader.js

@@ -1,4 +1,4 @@
-import * as THREE from "../../../libs/three.js/build/three.module.js";
+import * as THREE from "../../../../libs/three.js/build/three.module.js";
 
 /**
  * NVIDIA FXAA by Timothy Lottes

src/materials/postprocessing/LuminosityHighPassShader.js → src/custom/materials/postprocessing/LuminosityHighPassShader.js


src/materials/postprocessing/MaskPass.js → src/custom/materials/postprocessing/MaskPass.js


+ 1 - 1
src/materials/postprocessing/OutlinePass.js

@@ -1,7 +1,7 @@
 /**
  * @author spidersharma / http://eduperiment.com/
  */
-import * as THREE from "../../../libs/three.js/build/three.module.js";
+import * as THREE from "../../../../libs/three.js/build/three.module.js";
 import {Pass, ShaderPass} from './ShaderPass'
 import CopyShader from './CopyShader'
 

+ 1 - 1
src/materials/postprocessing/RenderPass.js

@@ -1,7 +1,7 @@
 /**
  * @author alteredq / http://alteredqualia.com/
  */
-import * as THREE from "../../../libs/three.js/build/three.module.js";
+import * as THREE from "../../../../libs/three.js/build/three.module.js";
 import {Pass} from './ShaderPass'
 
 class RenderPass extends Pass {

src/materials/postprocessing/SMAAPass.js → src/custom/materials/postprocessing/SMAAPass.js


src/materials/postprocessing/SMAAShader.js → src/custom/materials/postprocessing/SMAAShader.js


+ 1 - 1
src/materials/postprocessing/SSAARenderPass.js

@@ -17,7 +17,7 @@
 
 
 
-import * as THREE from "../../../libs/three.js/build/three.module.js";
+import * as THREE from "../../../../libs/three.js/build/three.module.js";
 import {Pass, ShaderPass} from './ShaderPass'
 import CopyShader from './CopyShader'
 

+ 1 - 1
src/materials/postprocessing/ShaderPass.js

@@ -1,7 +1,7 @@
 /**
  * @author alteredq / http://alteredqualia.com/
  */
-import * as THREE from "../../../libs/three.js/build/three.module.js";
+import * as THREE from "../../../../libs/three.js/build/three.module.js";
  
 
 let Pass = function () {

src/materials/postprocessing/TAARenderPass.js → src/custom/materials/postprocessing/TAARenderPass.js


src/materials/postprocessing/UnrealBloomPass.js → src/custom/materials/postprocessing/UnrealBloomPass.js


+ 2 - 0
src/custom/note.txt

@@ -8,7 +8,9 @@ start.js可访问全局变量Potree,引用当前目录的其他文件(都是
 start.js除了通过引用shim文件来修改Potree, 也可在此文件修改,更多是执行加载点云等程序。
 
 ------------------------
+问题:
 
+PointAttributes.js 为什么不改也可以?
 
 
 ----

+ 1 - 1
src/custom/potree.shim.js

@@ -650,7 +650,7 @@ Utils.getIntersect = function (camera, meshes, pointer, raycaster) {
     return n[0]
 } 
 
-BinaryLoader.prototype.load = function(node){
+BinaryLoader.prototype.load = function(node){//解析点云
     if (node.loaded) {
         return;
     }

+ 7 - 7
src/custom/viewer/ExtendViewer.js

@@ -48,13 +48,13 @@ import {MTLLoader} from "../../../libs/three.js/loaders/MTLLoader.js";
 import {GLTFLoader} from  "../../../libs/three.js/loaders/GLTFLoader.js";
  
 
-import SSAARenderPass from "../../materials/postprocessing/SSAARenderPass.js"
-import EffectComposer from '../../materials/postprocessing/EffectComposer.js'
-import {ShaderPass} from '../../materials/postprocessing/ShaderPass.js'
-import RenderPass from '../../materials/postprocessing/RenderPass.js'
-import FXAAShader from "../../materials/postprocessing/FXAAShader.js"
-import OutlinePass from "../../materials/postprocessing/OutlinePass.js"
-import BasicMaterial from '../../materials/BasicMaterial.js'  
+import SSAARenderPass from "../materials/postprocessing/SSAARenderPass.js"
+import EffectComposer from '../materials/postprocessing/EffectComposer.js'
+import {ShaderPass} from '../materials/postprocessing/ShaderPass.js'
+import RenderPass from '../materials/postprocessing/RenderPass.js'
+import FXAAShader from "../materials/postprocessing/FXAAShader.js"
+import OutlinePass from "../materials/postprocessing/OutlinePass.js"
+import BasicMaterial from '../materials/BasicMaterial.js'  
  
 //import {RoomEnvironment} from './RoomEnvironment.js'
 import {FirstPersonControls} from "../../navigation/FirstPersonControlsNew.js";

+ 2 - 1
src/loader/BinaryLoader.js

@@ -5,6 +5,7 @@ import {Version} from "../Version.js";
 import {XHRFactory} from "../XHRFactory.js";
 
 
+//加载 解析点云
 export class BinaryLoader{
 
 	constructor(version, boundingBox, scale){
@@ -52,7 +53,7 @@ export class BinaryLoader{
 		}
 	};
 
-	parse(node, buffer){
+	parse(node, buffer){//old
 		let pointAttributes = node.pcoGeometry.pointAttributes;
 		let numPoints = buffer.byteLength / node.pcoGeometry.pointAttributes.byteSize;
 

+ 7 - 83
src/loader/POCLoader.js

@@ -8,65 +8,6 @@ import {BinaryLoader} from "./BinaryLoader.js";
 import {Utils} from "../utils.js";
 import {PointAttribute, PointAttributes, PointAttributeTypes} from "./PointAttributes.js";
 
-
-var transformFrom4dkk = function(name){
-    var jsAttribute = PointAttribute[name] 
-    return jsAttribute
-    /* if(name == "POSITION_CARTESIAN"){
-        jsAttribute = {
-            description: "",
-            elementSize: 4,
-            elements: 3,
-            name: "POSITION_CARTESIAN",
-            size: 12,
-            type: "int32",
-        }
-    }else if(name == "COLOR_PACKED"){
-        jsAttribute = {
-            description: "" ,
-            elementSize: 1,
-            elements: 4,
-            name: "RGBA",
-            size: 4,
-            type: 'int8', 
-        }
-    }else if(name == "NORMAL_OCT16"){
-       
-        jsAttribute = {
-            description: "" ,
-            elementSize: 4,
-            elements: 2,
-            name: "NORMAL_OCT16",
-            size: 12,
-            type: "uint8",
-        }
-    } */
-    /*  var Q = q(L.COLOR_PACKED, K.DATA_TYPE_INT8, 4)
-    POSITION_CARTESIAN: q(L.POSITION_CARTESIAN, K.DATA_TYPE_FLOAT, 3),
-    RGBA_PACKED: Q,
-    COLOR_PACKED: Q,
-    RGB_PACKED: q(L.COLOR_PACKED, K.DATA_TYPE_INT8, 3),
-    NORMAL_FLOATS: q(L.NORMAL_FLOATS, K.DATA_TYPE_FLOAT, 3),
-    FILLER_1B: q(L.FILLER, K.DATA_TYPE_UINT8, 1),
-    INTENSITY: q(L.INTENSITY, K.DATA_TYPE_UINT16, 1),
-    CLASSIFICATION: q(L.CLASSIFICATION, K.DATA_TYPE_UINT8, 1),
-    NORMAL_SPHEREMAPPED: q(L.NORMAL_SPHEREMAPPED, K.DATA_TYPE_UINT8, 2),
-    NORMAL_OCT16: q(L.NORMAL_OCT16, K.DATA_TYPE_UINT8, 2),
-    NORMAL: q(L.NORMAL, K.DATA_TYPE_FLOAT, 3) */
-    
-}
-    
-
-
-
-
-
-
-
-
-
-
-
 function parseAttributes(cloudjs){
 
 	let version = new Version(cloudjs.version);
@@ -126,15 +67,7 @@ function parseAttributes(cloudjs){
 			float:  PointAttributeTypes.DATA_TYPE_FLOAT,
 		};
 
-		for(let jsAttribute of pointAttributes){
-            
-            if(jsAttribute.name == void 0){//是来自四维看看的数据
-                //attribute = transformFrom4dkk(jsAttribute)
-                var attribute_ = PointAttribute[jsAttribute] 
-                attributes.add(attribute_);
-                continue;
-            }
-            
+		for(const jsAttribute of pointAttributes){
 			const name = replaceOldNames(jsAttribute.name);
 			const type = typeConversion[jsAttribute.type];
 			const numElements = jsAttribute.elements;
@@ -185,14 +118,12 @@ function lasLazAttributes(fMno){
 
 export class POCLoader {
 
-	static load(url, timeStamp, callback){ //add timeStamp
+	static load(url, callback){
 		try {
 			let pco = new PointCloudOctreeGeometry();
-            pco.timeStamp = timeStamp
-            
 			pco.url = url;
 			let xhr = XHRFactory.createXMLHttpRequest();
-			xhr.open('GET', url+'?m='+timeStamp, true);  
+			xhr.open('GET', url, true);
 
 			xhr.onreadystatechange = function () {
 				if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 0)) {
@@ -217,27 +148,20 @@ export class POCLoader {
 					let boundingBox = new THREE.Box3(min, max);
 					let tightBoundingBox = boundingBox.clone();
 
-					if (fMno.tightBoundingBox) {//这个才是真实的bounding,前面那个bounding的size是个正方体,似乎取了最长边作为边长
+					if (fMno.tightBoundingBox) {
 						tightBoundingBox.min.copy(new THREE.Vector3(fMno.tightBoundingBox.lx, fMno.tightBoundingBox.ly, fMno.tightBoundingBox.lz));
 						tightBoundingBox.max.copy(new THREE.Vector3(fMno.tightBoundingBox.ux, fMno.tightBoundingBox.uy, fMno.tightBoundingBox.uz));
 					}
-                    
-					let offset = min.clone(); //将成为点云的position,被我用作旋转中心(但在点云中不那么居中,navvis也是这样, 这样可能是为了让模型在这数据的bounding上)
-
-
 
+					let offset = min.clone();
 
-					boundingBox.min.sub(offset);   //点云的真实坐标的min都是0,0,0吗(我看案例是,因绕角落旋转,也就是原点)
-                    
+					boundingBox.min.sub(offset);
 					boundingBox.max.sub(offset);
 
 					tightBoundingBox.min.sub(offset);
 					tightBoundingBox.max.sub(offset);
 
-                    //改
-					//pco.projection = fMno.projection ||  "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs ",
-                        //"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" //给地图
-                    
+					pco.projection = fMno.projection;
 					pco.boundingBox = boundingBox;
 					pco.tightBoundingBox = tightBoundingBox;
 					pco.boundingSphere = boundingBox.getBoundingSphere(new THREE.Sphere());

+ 293 - 0
src/loader/POCLoaderNew.js

@@ -0,0 +1,293 @@
+
+import * as THREE from "../../libs/three.js/build/three.module.js";
+import {PointCloudOctreeGeometry, PointCloudOctreeGeometryNode} from "../PointCloudOctreeGeometry.js";
+import {Version} from "../Version.js";
+import {XHRFactory} from "../XHRFactory.js";
+import {LasLazLoader} from "./LasLazLoader.js";
+import {BinaryLoader} from "./BinaryLoader.js";
+import {Utils} from "../utils.js";
+import {PointAttribute, PointAttributes, PointAttributeTypes} from "./PointAttributes.js";
+
+ 
+
+
+function parseAttributes(cloudjs){
+
+	let version = new Version(cloudjs.version);
+
+	const replacements = {
+		"COLOR_PACKED": "rgba",
+		"RGBA": "rgba",
+		"INTENSITY": "intensity",
+		"CLASSIFICATION": "classification",
+		"GPS_TIME": "gps-time",
+	};
+
+	const replaceOldNames = (old) => {
+		if(replacements[old]){
+			return replacements[old];
+		}else{
+			return old;
+		}
+	};
+
+	const pointAttributes = [];
+	if(version.upTo('1.7')){
+		
+		for(let attributeName of cloudjs.pointAttributes){
+			const oldAttribute = PointAttribute[attributeName];
+
+			const attribute = {
+				name: oldAttribute.name,
+				size: oldAttribute.byteSize,
+				elements: oldAttribute.numElements,
+				elementSize: oldAttribute.byteSize / oldAttribute.numElements,
+				type: oldAttribute.type.name,
+				description: "",
+			};
+
+			pointAttributes.push(attribute);
+		}
+
+	}else{
+		pointAttributes.push(...cloudjs.pointAttributes);
+	}
+
+
+	{
+		const attributes = new PointAttributes();
+
+		const typeConversion = {
+			int8:   PointAttributeTypes.DATA_TYPE_INT8,
+			int16:  PointAttributeTypes.DATA_TYPE_INT16,
+			int32:  PointAttributeTypes.DATA_TYPE_INT32,
+			int64:  PointAttributeTypes.DATA_TYPE_INT64,
+			uint8:  PointAttributeTypes.DATA_TYPE_UINT8,
+			uint16: PointAttributeTypes.DATA_TYPE_UINT16,
+			uint32: PointAttributeTypes.DATA_TYPE_UINT32,
+			uint64: PointAttributeTypes.DATA_TYPE_UINT64,
+			double: PointAttributeTypes.DATA_TYPE_DOUBLE,
+			float:  PointAttributeTypes.DATA_TYPE_FLOAT,
+		};
+
+		for(let jsAttribute of pointAttributes){
+            
+            if(jsAttribute.name == void 0){ //add 有的是这个,也有的不是(点云编辑页的)
+                var attribute_ = PointAttribute[jsAttribute] 
+                attributes.add(attribute_);
+                continue;
+            }
+            
+			const name = replaceOldNames(jsAttribute.name);
+			const type = typeConversion[jsAttribute.type];
+			const numElements = jsAttribute.elements;
+			const description = jsAttribute.description;
+
+			const attribute = new PointAttribute(name, type, numElements);
+
+			attributes.add(attribute);
+		}
+
+		{
+			// check if it has normals
+			let hasNormals = 
+				pointAttributes.find(a => a.name === "NormalX") !== undefined &&
+				pointAttributes.find(a => a.name === "NormalY") !== undefined &&
+				pointAttributes.find(a => a.name === "NormalZ") !== undefined;
+
+			if(hasNormals){
+				let vector = {
+					name: "NORMAL",
+					attributes: ["NormalX", "NormalY", "NormalZ"],
+				};
+				attributes.addVector(vector);
+			}
+		}
+
+		return attributes;
+	}
+
+}
+
+function lasLazAttributes(fMno){
+	const attributes = new PointAttributes();
+
+	attributes.add(PointAttribute.POSITION_CARTESIAN);
+	attributes.add(new PointAttribute("rgba", PointAttributeTypes.DATA_TYPE_UINT8, 4));
+	attributes.add(new PointAttribute("intensity", PointAttributeTypes.DATA_TYPE_UINT16, 1));
+	attributes.add(new PointAttribute("classification", PointAttributeTypes.DATA_TYPE_UINT8, 1));
+	attributes.add(new PointAttribute("gps-time", PointAttributeTypes.DATA_TYPE_DOUBLE, 1));
+	attributes.add(new PointAttribute("number of returns", PointAttributeTypes.DATA_TYPE_UINT8, 1));
+	attributes.add(new PointAttribute("return number", PointAttributeTypes.DATA_TYPE_UINT8, 1));
+	attributes.add(new PointAttribute("source id", PointAttributeTypes.DATA_TYPE_UINT16, 1));
+	//attributes.add(new PointAttribute("pointSourceID", PointAttributeTypes.DATA_TYPE_INT8, 4));
+
+
+	return attributes;
+}
+
+export class POCLoader {
+
+	static load(url, timeStamp, callback){ //add timeStamp
+		try {
+			let pco = new PointCloudOctreeGeometry();
+            pco.timeStamp = timeStamp
+            
+			pco.url = url;
+			let xhr = XHRFactory.createXMLHttpRequest();
+			xhr.open('GET', url+'?m='+timeStamp, true);  
+
+			xhr.onreadystatechange = function () {
+				if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 0)) {
+					let fMno = JSON.parse(xhr.responseText);
+
+					let version = new Version(fMno.version);
+
+					// assume octreeDir is absolute if it starts with http
+					if (fMno.octreeDir.indexOf('http') === 0) {
+						pco.octreeDir = fMno.octreeDir;
+					} else {
+						pco.octreeDir = url + '/../' + fMno.octreeDir;
+					}
+
+					pco.spacing = fMno.spacing;
+					pco.hierarchyStepSize = fMno.hierarchyStepSize;
+
+					pco.pointAttributes = fMno.pointAttributes;
+
+					let min = new THREE.Vector3(fMno.boundingBox.lx, fMno.boundingBox.ly, fMno.boundingBox.lz);
+					let max = new THREE.Vector3(fMno.boundingBox.ux, fMno.boundingBox.uy, fMno.boundingBox.uz);
+					let boundingBox = new THREE.Box3(min, max);
+					let tightBoundingBox = boundingBox.clone();
+
+					if (fMno.tightBoundingBox) {//这个才是真实的bounding,前面那个bounding的size是个正方体,似乎取了最长边作为边长
+						tightBoundingBox.min.copy(new THREE.Vector3(fMno.tightBoundingBox.lx, fMno.tightBoundingBox.ly, fMno.tightBoundingBox.lz));
+						tightBoundingBox.max.copy(new THREE.Vector3(fMno.tightBoundingBox.ux, fMno.tightBoundingBox.uy, fMno.tightBoundingBox.uz));
+					}
+                    
+					let offset = min.clone(); //将成为点云的position,被我用作旋转中心(但在点云中不那么居中,navvis也是这样, 这样可能是为了让模型在这数据的bounding上)
+
+
+
+
+					boundingBox.min.sub(offset);   //点云的真实坐标的min都是0,0,0吗(我看案例是,因绕角落旋转,也就是原点)
+                    
+					boundingBox.max.sub(offset);
+
+					tightBoundingBox.min.sub(offset);
+					tightBoundingBox.max.sub(offset);
+
+                    //改
+					//pco.projection = fMno.projection ||  "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs ",
+                        //"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" //给地图
+                    
+					pco.boundingBox = boundingBox;
+					pco.tightBoundingBox = tightBoundingBox;
+					pco.boundingSphere = boundingBox.getBoundingSphere(new THREE.Sphere());
+					pco.tightBoundingSphere = tightBoundingBox.getBoundingSphere(new THREE.Sphere());
+					pco.offset = offset;
+					if (fMno.pointAttributes === 'LAS') {
+						pco.loader = new LasLazLoader(fMno.version, "las");
+						pco.pointAttributes = lasLazAttributes(fMno);
+					} else if (fMno.pointAttributes === 'LAZ') {
+						pco.loader = new LasLazLoader(fMno.version, "laz");
+						pco.pointAttributes = lasLazAttributes(fMno);
+					} else {
+						pco.loader = new BinaryLoader(fMno.version, boundingBox, fMno.scale);
+						pco.pointAttributes = parseAttributes(fMno);
+					}
+
+					let nodes = {};
+
+					{ // load root
+						let name = 'r';
+
+						let root = new PointCloudOctreeGeometryNode(name, pco, boundingBox);
+						root.level = 0;
+						root.hasChildren = true;
+						root.spacing = pco.spacing;
+						if (version.upTo('1.5')) {
+							root.numPoints = fMno.hierarchy[0][1];
+						} else {
+							root.numPoints = 0;
+						}
+						pco.root = root;
+						pco.root.load();
+						nodes[name] = root;
+					}
+
+					// load remaining hierarchy
+					if (version.upTo('1.4')) {
+						for (let i = 1; i < fMno.hierarchy.length; i++) {
+							let name = fMno.hierarchy[i][0];
+							let numPoints = fMno.hierarchy[i][1];
+							let index = parseInt(name.charAt(name.length - 1));
+							let parentName = name.substring(0, name.length - 1);
+							let parentNode = nodes[parentName];
+							let level = name.length - 1;
+							//let boundingBox = POCLoader.createChildAABB(parentNode.boundingBox, index);
+							let boundingBox = Utils.createChildAABB(parentNode.boundingBox, index);
+
+							let node = new PointCloudOctreeGeometryNode(name, pco, boundingBox);
+							node.level = level;
+							node.numPoints = numPoints;
+							node.spacing = pco.spacing / Math.pow(2, level);
+							parentNode.addChild(node);
+							nodes[name] = node;
+						}
+					}
+
+					pco.nodes = nodes;
+
+					callback(pco);
+				}
+			};
+
+			xhr.send(null);
+		} catch (e) {
+			console.log("loading failed: '" + url + "'");
+			console.log(e);
+
+			callback();
+		}
+	}
+
+	loadPointAttributes(mno){
+		let fpa = mno.pointAttributes;
+		let pa = new PointAttributes();
+
+		for (let i = 0; i < fpa.length; i++) {
+			let pointAttribute = PointAttribute[fpa[i]];
+			pa.add(pointAttribute);
+		}
+
+		return pa;
+	}
+
+	createChildAABB(aabb, index){
+		let min = aabb.min.clone();
+		let max = aabb.max.clone();
+		let size = new THREE.Vector3().subVectors(max, min);
+
+		if ((index & 0b0001) > 0) {
+			min.z += size.z / 2;
+		} else {
+			max.z -= size.z / 2;
+		}
+
+		if ((index & 0b0010) > 0) {
+			min.y += size.y / 2;
+		} else {
+			max.y -= size.y / 2;
+		}
+
+		if ((index & 0b0100) > 0) {
+			min.x += size.x / 2;
+		} else {
+			max.x -= size.x / 2;
+		}
+
+		return new THREE.Box3(min, max);
+	}
+}
+

+ 297 - 0
src/materials/ExtendPointCloudMaterial.js

@@ -0,0 +1,297 @@
+
+import * as THREE from "../../libs/three.js/build/three.module.js";
+import {Utils} from "../utils.js";
+import {Gradients} from "./Gradients.js";
+import {Shaders} from "../../build/shaders/shaders.js";
+import {ClassificationScheme} from "./ClassificationScheme.js";
+import {PointSizeType, PointShape, TreeType, ElevationGradientRepeat} from "../defines.js";
+import {Features} from "../Features.js";
+import {PointCloudMaterial} from './PointCloudMaterial.js'
+
+//
+// how to calculate the radius of a projected sphere in screen space
+// http://stackoverflow.com/questions/21648630/radius-of-projected-sphere-in-screen-space
+// http://stackoverflow.com/questions/3717226/radius-of-projected-sphere
+//
+
+
+export class ExtendPointCloudMaterial extends PointCloudMaterial {
+	constructor (parameters = {}) {
+		super(parameters);
+ 
+
+		let getValid = (a, b) => {
+			if(a !== undefined){
+				return a;
+			}else{
+				return b;
+			}
+		}
+ 
+		let maxSize = getValid(parameters.maxSize, 1550.0);
+		  
+		this._gradient = Gradients.RAINBOW//Gradients.SPECTRAL;//海拔贴图种类
+		this.gradientTexture = ExtendPointCloudMaterial.generateGradientTexture(this._gradient); 
+		//this.matcapTexture = ExtendPointCloudMaterial.generateMatcapTexture(this._matcap);
+
+        delete this.uniforms.screenWidth
+        delete this.uniforms.screenHeight
+        Object.assign(this.uniforms,{
+            resolution:    { type: 'v2',  value: new THREE.Vector2() },
+            maxSize:			{ type: "f", value: maxSize },
+            gradient:			{ type: "t", value: this.gradientTexture },
+			progress: {
+				type: "f",
+				value: 0
+			},
+            easeInOutRatio:{
+                type: "f",
+				value: 0.3
+            },
+			pano0Map: {
+				type: "t",
+				value: null
+			},
+			pano0Position: {
+				type: "v3",
+				value: new THREE.Vector3
+			},
+			pano0Matrix: {
+				type: "m4",
+				value: new THREE.Matrix4
+			},
+			pano1Map: {
+				type: "t",
+				value: null
+			},
+			pano1Position: {
+				type: "v3",
+				value: new THREE.Vector3
+			},
+			pano1Matrix: {
+				type: "m4",
+				value: new THREE.Matrix4
+            },   
+        })
+        
+         
+
+		 
+		this.updateShaderSource();
+	}
+
+ 
+ 
+
+	updateShaderSource () {  
+
+        let vs = Shaders['pointcloud_new.vs']; //改
+		let fs = Shaders['pointcloud_new.fs']; //改
+		let definesString = this.getDefines();
+
+		let vsVersionIndex = vs.indexOf("#version ");
+		let fsVersionIndex = fs.indexOf("#version ");
+
+		if(vsVersionIndex >= 0){
+			vs = vs.replace(/(#version .*)/, `$1\n${definesString}`)
+		}else{
+			vs = `${definesString}\n${vs}`;
+		}
+
+		if(fsVersionIndex >= 0){
+			fs = fs.replace(/(#version .*)/, `$1\n${definesString}`)
+		}else{
+			fs = `${definesString}\n${fs}`;
+		}
+
+		this.vertexShader = vs;
+		this.fragmentShader = fs;
+
+		if (this.opacity === 1.0 && !this.useFilterByNormal) {//add useFilterByNormal
+			this.blending = THREE.NoBlending;
+			this.transparent = false;
+			this.depthTest = true;
+			this.depthWrite = true;
+			this.depthFunc = THREE.LessEqualDepth;
+		} else if (  (this.opacity < 1.0 ||this.useFilterByNormal) &&   !this.useEDL) {//add useFilterByNormal
+			this.blending = THREE.AdditiveBlending;
+			this.transparent = true;
+			this.depthTest = false;
+			this.depthWrite = true;
+			this.depthFunc = THREE.AlwaysDepth;
+		}
+
+		if (this.weighted) {
+			this.blending = THREE.AdditiveBlending;
+			this.transparent = true;
+			this.depthTest = true;
+			this.depthWrite = false;
+		}
+
+		this.needsUpdate = true;
+	}
+
+	getDefines () {
+		let defines = [];
+ 
+		if (this.pointSizeType === PointSizeType.FIXED) {
+			defines.push('#define fixed_point_size');
+		} else if (this.pointSizeType === PointSizeType.ATTENUATED) {
+			defines.push('#define attenuated_point_size');
+		} else if (this.pointSizeType === PointSizeType.ADAPTIVE) {
+			defines.push('#define adaptive_point_size');
+		}
+        
+        if(!Features.EXT_DEPTH.isSupported() && this.shape === PointShape.PARABOLOID){
+            this.shape = PointShape.SQUARE ;//强行替换
+        }
+        
+        
+		if (this.shape === PointShape.SQUARE) {
+			defines.push('#define square_point_shape');
+		} else if (this.shape === PointShape.CIRCLE) {
+			defines.push('#define circle_point_shape');
+		}  else if (this.shape === PointShape.PARABOLOID) { 
+			defines.push('#define paraboloid_point_shape');
+		}  
+        //console.log('this.shape PARABOLOID', this.shape, this.shape === PointShape.PARABOLOID)
+
+		if (this._useEDL || this.fakeEDL) {
+			defines.push('#define use_edl');
+		}
+
+		if(this.activeAttributeName){
+			let attributeName = this.activeAttributeName.replace(/[^a-zA-Z0-9]/g, '_');
+
+			defines.push(`#define color_type_${attributeName}`);
+		}
+		
+		if(this._treeType === TreeType.OCTREE){
+			defines.push('#define tree_type_octree');
+		}else if(this._treeType === TreeType.KDTREE){
+			defines.push('#define tree_type_kdtree');
+		}
+
+		if (this.weighted) {
+			defines.push('#define weighted_splats');
+		}
+
+		for(let [key, value] of this.defines){
+			defines.push(value);
+		}
+
+		return defines.join("\n");
+	}
+
+	 
+
+	  
+	get pointSizeType () {
+		return this._pointSizeType;
+	}
+ 
+ 
+
+	set pointSizeType (value) {
+        
+        if(typeof value == 'string' )value = PointSizeType[value]
+        super.pointSizeType = value
+		/* if (this._pointSizeType !== value) {
+			this._pointSizeType = value;
+			this.updateShaderSource();              //这句表明这个属性频繁更改会卡顿
+			this.dispatchEvent({
+				type: 'point_size_type_changed',
+				target: this
+			});
+			this.dispatchEvent({
+				type: 'material_property_changed',
+				target: this
+			});
+		} */
+	}
+
+	 
+    get color () {
+		return this.uniforms.uColor.value;
+	}
+     
+
+	set color (value) {//改
+        
+        if(value == this.color_)return
+        let color = value;
+		//if (!this.uniforms.uColor.value.equals(value)) {
+        if(typeof value == 'string') {
+            var colorArr = Potree.config.colors[value]  
+            if(!colorArr){ 
+                //console.warn('没找到该颜色值'+ value)
+            }else{
+                color = new THREE.Color().fromArray(colorArr).multiplyScalar(1/255)
+            }                
+            
+        }    
+        this.uniforms.uColor.value.set(color)  
+        //this.uniforms.uColor.value.copy(value);
+			
+        this.dispatchEvent({
+            type: 'color_changed',
+            target: this
+        });
+        this.dispatchEvent({
+            type: 'material_property_changed',
+            target: this
+        });
+		//}
+        
+        this.color_ = value //记录下str
+	}
+
+	 
+	 
+	
+	 
+	 
+
+    ////////////////////////add
+    setProjectedPanos(pano0, pano1, progressValue, easeInOutRatio){
+        
+        //this.uniforms.usePanoMap.value = 1
+        this.usePanoMap = true
+        
+ 		progressValue!=void 0 && (this.uniforms.progress.value = progressValue);
+		//pano0.ensureSkyboxReadyForRender();
+		this.uniforms.pano0Map.value = pano0.getSkyboxTexture()
+		this.uniforms.pano0Position.value.copy(pano0.position)
+		this.uniforms.pano0Matrix.value.copy(pano0.panoMatrix  );
+		//pano1.ensureSkyboxReadyForRender();
+ 
+        this.uniforms.easeInOutRatio.value =  easeInOutRatio || 0; //之前做点云和全景混合时加的,为了让点云颜色柔和切换到全景颜色。如不混合就0
+		
+		this.uniforms.pano1Map.value = pano1.getSkyboxTexture()
+		this.uniforms.pano1Position.value.copy(pano1.position)
+		this.uniforms.pano1Matrix.value.copy(pano1.panoMatrix   );
+           
+        //this.updateShaderSource()
+        //this.needsUpdate = true;
+ 	}
+    stopProjectedPanos(){
+        //this.uniforms.usePanoMap.value = 0
+        this.usePanoMap = false
+    } 
+
+	// copyFrom(from){
+
+	// 	var a = 10;
+
+	// 	for(let name of Object.keys(this.uniforms)){
+	// 		this.uniforms[name].value = from.uniforms[name].value;
+	// 	}
+	// }
+
+	// copy(from){
+	// 	this.copyFrom(from);
+	// }
+    
+    
+
+}

+ 2 - 0
src/utils/Measure.js

@@ -6,6 +6,8 @@ import {Line2} from "../../libs/three.js/lines/Line2.js";
 import {LineGeometry} from "../../libs/three.js/lines/LineGeometry.js";
 import {LineMaterial} from "../../libs/three.js/lines/LineMaterial.js";
 
+
+//old
 function createHeightLine(){
 	let lineGeometry = new LineGeometry();
 

+ 2 - 0
src/utils/MeasuringTool.js

@@ -5,6 +5,8 @@ import {Utils} from "../utils.js";
 import {CameraMode} from "../defines.js";
 import { EventDispatcher } from "../EventDispatcher.js";
 
+
+//old
 function updateAzimuth(viewer, measure){
 
 	const azimuth = measure.azimuth;