|
|
@@ -53390,35 +53390,34 @@
|
|
|
|
|
|
,
|
|
|
|
|
|
- CloneObject : function(copyObj, result, isSimpleCopy, simpleCopyList=[]) {
|
|
|
+ CloneObject : function (copyObj, isSimpleCopy, simpleCopyList = [], judgeSimpleCopyFun) {
|
|
|
//isSimpleCopy 只复制最外层
|
|
|
- //复制json result的可能:普通数字或字符串、普通数组、复杂对象
|
|
|
-
|
|
|
- simpleCopyList.push(Object3D); //遇到simpleCopyList中的类直接使用不拷贝
|
|
|
+ //复制json result的可能:普通数字或字符串、普通数组、复杂对象
|
|
|
+ judgeSimpleCopyFun || (judgeSimpleCopyFun=()=>{});
|
|
|
|
|
|
- if(!copyObj || typeof copyObj == 'number' || typeof copyObj == 'string' || copyObj instanceof Function || simpleCopyList.some(className => copyObj instanceof className)){
|
|
|
- return copyObj
|
|
|
+ if (!copyObj || typeof copyObj == 'number' || typeof copyObj == 'string' ||copyObj.isObject3D || copyObj instanceof Function || simpleCopyList.some(className => copyObj instanceof className) || judgeSimpleCopyFun(copyObj)) {
|
|
|
+ return copyObj
|
|
|
}
|
|
|
-
|
|
|
- result = result || {};
|
|
|
+
|
|
|
if (copyObj instanceof Array) {
|
|
|
- return copyObj.map(e=>{
|
|
|
- return this.CloneObject(e)
|
|
|
- })
|
|
|
- }else {
|
|
|
- if(copyObj.clone instanceof Function ){ //解决一部分
|
|
|
+ return copyObj.map(e => {
|
|
|
+ return this.CloneObject(e, isSimpleCopy, simpleCopyList, judgeSimpleCopyFun)
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ if (copyObj.clone instanceof Function) {
|
|
|
+ //解决一部分
|
|
|
return copyObj.clone()
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ let result = {};
|
|
|
for (var key in copyObj) {
|
|
|
- if (copyObj[key] instanceof Object && !isSimpleCopy)
|
|
|
- result[key] = this.CloneObject(copyObj[key]);
|
|
|
- else
|
|
|
- result[key] = copyObj[key];
|
|
|
+ if (copyObj[key] instanceof Object && !isSimpleCopy ) result[key] = this.CloneObject(copyObj[key], isSimpleCopy, simpleCopyList, judgeSimpleCopyFun);
|
|
|
+ else result[key] = copyObj[key];
|
|
|
//如果是函数类同基本数据,即复制引用
|
|
|
}
|
|
|
- return result;
|
|
|
- }
|
|
|
+ return result
|
|
|
+ }
|
|
|
,
|
|
|
CloneClassObject :function(copyObj, {ignoreList=[],simpleCopyList=[]}={}){//复杂类对象
|
|
|
var newobj = new copyObj.constructor();
|
|
|
@@ -53438,7 +53437,7 @@
|
|
|
}else if(simpleCopyList.includes(i)){
|
|
|
targetObj[i] = copyObj[i];
|
|
|
}else {
|
|
|
- targetObj[i] = this.CloneObject(copyObj[i], null, false, simpleCopyList );
|
|
|
+ targetObj[i] = this.CloneObject(copyObj[i], false, simpleCopyList );
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -53497,12 +53496,6 @@
|
|
|
|
|
|
}
|
|
|
,
|
|
|
- replaceAll : function (str, f, e) {
|
|
|
- //f全部替换成e
|
|
|
- var reg = new RegExp(f, "g"); //创建正则RegExp对象
|
|
|
- return str.replace(reg, e);
|
|
|
- }
|
|
|
- ,
|
|
|
downloadFile : function(data, filename, cb) {
|
|
|
var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
|
|
|
save_link.href = data;
|
|
|
@@ -53512,15 +53505,59 @@
|
|
|
save_link.dispatchEvent(event);
|
|
|
cb && cb();
|
|
|
},
|
|
|
+
|
|
|
+ replaceAll : function (str, f, e ) {
|
|
|
+ //f全部替换成e
|
|
|
+
|
|
|
+ if(str.replaceAll ) return str.replaceAll(f, e)
|
|
|
+ else {
|
|
|
+ let escapeRegExp = (string)=>{
|
|
|
+ return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
|
|
+ };
|
|
|
+
|
|
|
+ return str.replace(new RegExp(escapeRegExp(f), 'g'), e);
|
|
|
+
|
|
|
+ /* var reg = new RegExp(f, "g"); //创建正则RegExp对象 这个没法转换'('
|
|
|
+ return str.replace(reg, e); //str.split(f).join(e); */
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- dealURL(url){
|
|
|
- return this.replaceAll(url, "\\+", "%2B");// 浏览器似乎不支持访问带+的地址
|
|
|
+
|
|
|
+ cleanUrl(url){//斜杠处理 协议aaa://保留双斜杠,其余单斜杠
|
|
|
+ //分离协议和路径部分
|
|
|
+ const protocolMatch = url.match(/^(\w+:)\/{2,}/);
|
|
|
+
|
|
|
+ if (protocolMatch) {
|
|
|
+ const protocol = protocolMatch[1];
|
|
|
+ const path = url.slice(protocolMatch[0].length);
|
|
|
+ return protocol + '//' + path.replace(/\/+/g, '/');
|
|
|
+ } else {
|
|
|
+ return url.replace(/\/+/g, '/');
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ joinUrl(){//拼接地址。总是出现前后多个/造成双斜杠或者缺斜杠的问题,处理一下
|
|
|
+ return this.cleanUrl(Array.from(arguments).join('/'))
|
|
|
+ },
|
|
|
+
|
|
|
+ dealURL(url=''){
|
|
|
+ let urlNew = this.replaceAll(url, "+", "%2B"); //this.replaceAll(url, "\\+", "%2B");// 浏览器似乎不支持访问带+的地址
|
|
|
+
|
|
|
+ urlNew = this.replaceAll(urlNew, "/.//", "/"); //去除双斜杠(/.//)
|
|
|
+
|
|
|
+
|
|
|
+ //urlNew = encodeURIComponent(url)
|
|
|
+
|
|
|
+ return urlNew
|
|
|
},
|
|
|
|
|
|
|
|
|
- getNameFromURL(url){
|
|
|
+ getNameFromURL(url, removePostfix){
|
|
|
+ if(!url)return ''
|
|
|
let get = (e)=>{
|
|
|
- return e.split('/').pop()
|
|
|
+ let a = e.split('/').pop();
|
|
|
+ if(removePostfix) a = a.split('.')[0];
|
|
|
+ return a
|
|
|
};
|
|
|
if(url instanceof Array){
|
|
|
return url.map(e=>get(e))
|
|
|
@@ -53538,35 +53575,31 @@
|
|
|
|
|
|
intervalTool:{ //延时update,防止卡顿
|
|
|
list:[],
|
|
|
-
|
|
|
- /* isWaiting:function(name, func, delayTime ){
|
|
|
- let item = this.list.find(e=>e.name == name)
|
|
|
- if(!item){ //如果没有该项, 则加入循环
|
|
|
- let ifContinue = func()
|
|
|
- item = {name}
|
|
|
- this.list.push(item);
|
|
|
- setTimeout(()=>{
|
|
|
- var a = this.list.indexOf(item);
|
|
|
+
|
|
|
+ /* isWaiting:function(name, func, delayTime){
|
|
|
+ if(!this.list.includes(name)){ //如果没有该项, 则开始判断
|
|
|
+ var needWait = func(); //触发了改变,则等待一段时间后再自动判断
|
|
|
+ if(needWait){
|
|
|
+ this.list.push(name);
|
|
|
+ setTimeout(()=>{
|
|
|
+ var a = this.list.indexOf(name);
|
|
|
this.list.splice(a,1);
|
|
|
- if(item.requestUpdate || ifContinue ) this.isWaiting(name, func, delayTime) //循环
|
|
|
+ this.isWaiting(name, func, delayTime) //循环
|
|
|
},delayTime)
|
|
|
-
|
|
|
- }else{//如果有该项,说明现在请求下一次继续更新
|
|
|
- //if(delayTime == 0){//想立刻更新一次
|
|
|
- // func()
|
|
|
- //}else{
|
|
|
- item.requestUpdate = true
|
|
|
- //}
|
|
|
-
|
|
|
+ }
|
|
|
}
|
|
|
}, */
|
|
|
|
|
|
|
|
|
+
|
|
|
isWaiting:function(name, func, delayTime/* , autoCycle */){
|
|
|
let item = this.list.find(e=>e.name == name);
|
|
|
if(!item){ //如果没有该项, 则加入循环
|
|
|
let ifContinue = func();
|
|
|
item = {name, func, delayTime};
|
|
|
+ /* if(name == 'processPriorityQueue'){
|
|
|
+ console.log('isWaiting', delayTime)
|
|
|
+ } */
|
|
|
this.list.push(item);
|
|
|
setTimeout(()=>{
|
|
|
var a = this.list.indexOf(item);
|
|
|
@@ -53582,24 +53615,64 @@
|
|
|
//更新属性
|
|
|
item.func = func;
|
|
|
item.delayTime = delayTime;
|
|
|
- item.requestUpdate = true;
|
|
|
-
|
|
|
-
|
|
|
- //}
|
|
|
-
|
|
|
+ item.requestUpdate = true;
|
|
|
+ //}
|
|
|
+ }
|
|
|
+ },
|
|
|
+ }
|
|
|
+ ,
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ waitTool:{//定时器,在等待的这段时间内如果又触发则重新计时
|
|
|
+ list:[],
|
|
|
+
|
|
|
+ wait(name, func, time){
|
|
|
+ let item = this.list.find(e=>e.name == name);
|
|
|
+
|
|
|
+ let timer = setTimeout(()=>{
|
|
|
+ func();
|
|
|
+ let index = this.list.indexOf(item);
|
|
|
+ this.list.splice(index, 1);
|
|
|
+ }, time);
|
|
|
+ if(item){
|
|
|
+ clearTimeout(item.timer);
|
|
|
+ }else {
|
|
|
+ item = {name};
|
|
|
+ this.list.push(item);
|
|
|
}
|
|
|
+ item.timer = timer;
|
|
|
},
|
|
|
|
|
|
+ cancel(name){
|
|
|
+ let index = this.list.findIndex(e=>e.name == name);
|
|
|
+ index>-1 && this.list.splice(index, 1);
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
,
|
|
|
- pushToGroupAuto : function(items, groups, recognizeFunction){//自动分组。 items是将分到一起的组合。items.length = 1 or 2.
|
|
|
+ pushToGroupAuto : function(items, groups, recognizeFunction, recognizeGroup){//自动分组。 items是将分到一起的组合。items.length = 1 or 2.
|
|
|
|
|
|
recognizeFunction = recognizeFunction || function(){};
|
|
|
|
|
|
- var atGroups = groups.filter(group=>group.find(
|
|
|
- item => items[0] == item || recognizeFunction(item, items[0]) || items[1] == item || items[1] && recognizeFunction(item, items[1])
|
|
|
|
|
|
- ));
|
|
|
+ if(recognizeGroup){ //有更复杂的识别处理,直接传递整个组
|
|
|
+ var atGroups = groups.filter(group=>recognizeGroup(group, items));
|
|
|
+
|
|
|
+ }else {
|
|
|
+ var atGroups = groups.filter(group=>group.find(
|
|
|
+ item => items[0] == item || recognizeFunction(item, items[0]) || items[1] == item || items[1] && recognizeFunction(item, items[1])
|
|
|
+ ));
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
if(atGroups.length){//在不同组
|
|
|
//因为items是一组的,所以先都放入组1
|
|
|
items.forEach(item=> {if(!atGroups[0].includes(item)) atGroups[0].push(item);});
|
|
|
@@ -53619,30 +53692,58 @@
|
|
|
}
|
|
|
},
|
|
|
|
|
|
-
|
|
|
-
|
|
|
- getBestCount : function(name, minCount=1,maxCount=6, durBound1 = 1.2, durBound2 = 10, ifLog){
|
|
|
-
|
|
|
+
|
|
|
+ getBestCount : (function(){
|
|
|
+ let lastCount = {};
|
|
|
+ return function(name, minCount=1,maxCount=6, durBound1 = 1.2, durBound2 = 10, ifLog, maxHistory){
|
|
|
+ let timeStamp = performance.getEntriesByName("loop-start");
|
|
|
+ let count;
|
|
|
+ if(timeStamp.length){
|
|
|
+ let dur = performance.now() - timeStamp[timeStamp.length-1].startTime; //dur在iphoneX中静止有7,pc是2
|
|
|
+
|
|
|
+ count = Math.round(math.linearClamp(dur, [durBound1,durBound2], [maxCount, minCount]));
|
|
|
+
|
|
|
+ if (maxHistory) {
|
|
|
+ if (!lastCount[name]) lastCount[name] = [];
|
|
|
+ if (count == 0 && lastCount[name].length > maxHistory - 1 && !lastCount[name].some(e => e > 0)) {
|
|
|
+ count = 1;
|
|
|
+ }
|
|
|
+ lastCount[name].push(count);
|
|
|
+ if (lastCount[name].length > maxHistory) lastCount[name].splice(0, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if(ifLog){//注意,console.log本身用时挺高, 降4倍时可能占用0.5毫秒
|
|
|
+ name && count && console.log(name, count , ' ,dur:', dur.toFixed(3));
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ count = maxCount; // ?
|
|
|
+ }
|
|
|
+ //主要在手机端有效果。
|
|
|
+ return count
|
|
|
+ }
|
|
|
+ })(),
|
|
|
+
|
|
|
+ getBestCountFPS(name, ifLog, minCount=1, maxCount=6, minFps = 10, maxFps = 60, minPanoCount = 200, maxPanoCount = 1000 ){
|
|
|
+
|
|
|
+ let fps = Potree.fps;
|
|
|
+
|
|
|
+ let count = math.linearClamp(fps, [minFps, maxFps], [minCount, maxCount]);
|
|
|
+
|
|
|
+ let count2 = math.linearClamp(viewer.images360.panos.length, [minPanoCount, maxPanoCount], [minCount, maxCount]);
|
|
|
+ count = (count + count2)/2;
|
|
|
|
|
|
- let timeStamp = performance.getEntriesByName("loop-start");
|
|
|
- let count;
|
|
|
- if(timeStamp.length){
|
|
|
- let dur = performance.now() - timeStamp[timeStamp.length-1].startTime; //dur在iphoneX中静止有7,pc是2
|
|
|
-
|
|
|
- count = Math.round(math.linearClamp(dur, durBound1,durBound2, maxCount, minCount));
|
|
|
-
|
|
|
- if(ifLog){//注意,console.log本身用时挺高, 降4倍时可能占用0.5毫秒
|
|
|
- name && count && console.log(name, count , ' ,dur:', dur.toFixed(3));
|
|
|
- }
|
|
|
- }else {
|
|
|
- count = maxCount; // ?
|
|
|
- }
|
|
|
+ count = Math.round(count);
|
|
|
+
|
|
|
+
|
|
|
+ if(ifLog){
|
|
|
+ name && count && console.log(name, count , ' ,fps:', fps.toFixed(3));
|
|
|
+ }
|
|
|
+
|
|
|
+ return count
|
|
|
|
|
|
- //主要在手机端有效果。
|
|
|
- return count
|
|
|
},
|
|
|
-
|
|
|
-
|
|
|
|
|
|
batchHandling : {//分批处理
|
|
|
|
|
|
@@ -53708,6 +53809,20 @@
|
|
|
|
|
|
},
|
|
|
|
|
|
+ getRootWindow(){//获取包含Potree的根window
|
|
|
+ let win = window;
|
|
|
+ try{
|
|
|
+ while(win.parent!=win && win.parent.Potree){
|
|
|
+ win = win.parent;
|
|
|
+ }
|
|
|
+ if(window != win)return win
|
|
|
+ }catch(e){
|
|
|
+ //console.log(e) //可能跨域,从而win.parent.Potree报错
|
|
|
+ console.log('getRootWindow 跨域');
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
|
|
|
watch: function(object, propName, initialValue){ //监听某个属性的变化
|
|
|
let v = initialValue;
|
|
|
@@ -53722,8 +53837,189 @@
|
|
|
});
|
|
|
},
|
|
|
|
|
|
+ imgAddLabel : function (img, labelImg, labelInfo = {}) {
|
|
|
+ //图上加另一张小图,用于添加水印
|
|
|
+ let canvas;
|
|
|
+ if(img instanceof Image){
|
|
|
+ canvas = document.createElement('canvas');
|
|
|
+ }else {
|
|
|
+ canvas = img;
|
|
|
+ }
|
|
|
+
|
|
|
+ let context = canvas.getContext('2d');
|
|
|
+ let marginLeft = labelInfo.bgMargin && labelInfo.bgMargin.left || 0;
|
|
|
+ let marginRight = labelInfo.bgMargin && labelInfo.bgMargin.right || 0;
|
|
|
+ let marginTop = labelInfo.bgMargin && labelInfo.bgMargin.top || 0;
|
|
|
+ let marginBottom = labelInfo.bgMargin && labelInfo.bgMargin.bottom || 0;
|
|
|
+
|
|
|
+ if(img instanceof Image){//如果img是canvas,说明已绘制在canvas上了就不用绘制了
|
|
|
+ let width = img.width + marginLeft + marginRight;
|
|
|
+ let height = img.height + marginTop + marginBottom;
|
|
|
+ canvas.width = width;
|
|
|
+ canvas.height = height;
|
|
|
+ if(labelInfo.bgColor){
|
|
|
+ context.fillStyle = 'rgba(' + labelInfo.bgColor.r + ',' + labelInfo.bgColor.g + ',' + labelInfo.bgColor.b + ',' + labelInfo.bgColor.a + ')';
|
|
|
+ context.fillRect(0,0,width,height);
|
|
|
+ }
|
|
|
+ context.drawImage(img, marginLeft, marginTop, img.width, img.height);
|
|
|
+ }
|
|
|
+ let labelWidth = labelInfo.widthRatioToImg ? img.width * labelInfo.widthRatioToImg : labelImg.width; //widthRatioToImg:label的width占img的width的比例
|
|
|
+ let labelHeight = (labelWidth * labelImg.height) / labelImg.width;
|
|
|
+
|
|
|
+ if (labelInfo.leftRatioToImg == void 0 && labelInfo.rightRatioToImg != void 0) {
|
|
|
+ labelInfo.leftRatioToImg = 1 - labelInfo.rightRatioToImg - (labelInfo.widthRatioToImg || labelImg.width / img.width);
|
|
|
+ }
|
|
|
+ if (labelInfo.topRatioToImg == void 0 && labelInfo.bottomRatioToImg != void 0) {
|
|
|
+ labelInfo.topRatioToImg = 1 - labelInfo.bottomRatioToImg - labelHeight / img.height;
|
|
|
+ }
|
|
|
+
|
|
|
+ let labelLeft = img.width * labelInfo.leftRatioToImg + marginLeft; //leftRatioToImg:label的left占img的width的比例
|
|
|
+ let labelTop = img.height * labelInfo.topRatioToImg + marginTop; //topRatioToImg:label的top占img的height的比例
|
|
|
+
|
|
|
+ context.globalAlpha = labelInfo.opacity != void 0 ? labelInfo.opacity : 1;
|
|
|
+ context.drawImage(labelImg, labelLeft, labelTop, labelWidth, labelHeight);
|
|
|
+
|
|
|
+ if(labelInfo.outputCanvas){
|
|
|
+ return canvas
|
|
|
+ }
|
|
|
+
|
|
|
+ var dataUrl = canvas.toDataURL('image/png', labelInfo.compressRatio);
|
|
|
+ //Common.downloadFile(dataUrl, 'screenshot.png')
|
|
|
+ context.clearRect(0,0,canvas.width,canvas.height);
|
|
|
+ return dataUrl
|
|
|
+
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
|
|
|
+ mobileAutoPlay(media, playFun){//移动端。不这么写video不会播放 . (2022.11.29: 可为何加了Hot.updateHots之后又会自动播了?https有关?
|
|
|
+
|
|
|
+
|
|
|
+ if(this.autoPlayList.includes(media))return
|
|
|
+ this.autoPlayList.push(media);
|
|
|
+ viewer.addEventListener;
|
|
|
+ let events = ['global_touchstart','global_mousedown'];
|
|
|
+
|
|
|
+ let fun = ()=>{
|
|
|
+ let index = this.autoPlayList.indexOf(media);
|
|
|
+ if(index>-1){
|
|
|
+
|
|
|
+ console.log( 'try autoplay '+ media.src);
|
|
|
+ playFun();
|
|
|
+ this.autoPlayList.splice(index,1);
|
|
|
+ events.forEach((eventName)=>{
|
|
|
+ viewer.removeEventListener(eventName,fun);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
|
|
|
+ events.forEach((eventName)=>{
|
|
|
+ viewer.addEventListener(eventName,fun);
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ /* changeShaderToWebgl2(vs, fs, matType, otherReplaces=[]){//部分shader要根据webgl版本作更改
|
|
|
+ if(!Potree.settings.isWebgl2)return {vs, fs}
|
|
|
+ let turnTo300 = matType != 'ShaderMaterial' && (vs.includes('gl_FragDepthEXT') || fs.includes('gl_FragDepthEXT') )
|
|
|
+ let addV300 = turnTo300 && matType != 'RawShaderMaterial' // RawShaderMaterial直接material.glslVersion = '300 es' 以加在define之前
|
|
|
+ let change = (shader, shaderType)=>{
|
|
|
+ let newShader = shader
|
|
|
+
|
|
|
+ if(turnTo300){ //非shaderMaterial需要手动改为300 es的写法
|
|
|
+ addV300 && (newShader = '#version 300 es \n' + newShader) //需要加 #version 300 es。 three.js自带的渲染会自动加所以不用
|
|
|
+ newShader = newShader.replaceAll('varying ', shaderType == 'vs' ? 'out ' : 'in ')
|
|
|
+ newShader = newShader.replaceAll('attribute ', 'in ')
|
|
|
+ if(shaderType == 'fs'){
|
|
|
+ newShader = newShader.replaceAll('gl_FragColor', 'fragColor')
|
|
|
+ newShader = newShader.replace('void main', 'out vec4 fragColor;\n void main' )//在void main前加入这个声明
|
|
|
+ }
|
|
|
+ newShader = newShader.replaceAll('gl_FragDepthEXT','gl_FragDepth')
|
|
|
+
|
|
|
+ newShader = newShader.replaceAll('texture2D','texture')
|
|
|
+ newShader = newShader.replaceAll('textureCube','texture')
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ newShader = newShader.replace('#extension GL_EXT_frag_depth : enable','')
|
|
|
+ newShader = newShader.replaceAll('defined(GL_EXT_frag_depth) &&','')
|
|
|
+
|
|
|
+
|
|
|
+ otherReplaces.forEach(({oldStr,newStr})=>{
|
|
|
+ newShader = newShader.replaceAll(oldStr,newStr)
|
|
|
+ })
|
|
|
+
|
|
|
+ return newShader
|
|
|
+ }
|
|
|
+
|
|
|
+ vs = change(vs,'vs')
|
|
|
+ fs = change(fs,'fs')
|
|
|
+
|
|
|
+ //console.log('成功替换为webgl2' )
|
|
|
+ return {vs,fs}
|
|
|
+ }//three.js的shaderMaterial也有替换功能,搜 '#define gl_FragDepthEXT gl_FragDepth',
|
|
|
+ */
|
|
|
+ changeShaderToWebgl2(vs, fs, matType, otherReplaces=[]){//部分shader要根据webgl版本作更改
|
|
|
+ if(!Potree.settings.isWebgl2)return {vs, fs}
|
|
|
+ let turnTo300 = matType != 'ShaderMaterial' && (vs.includes('gl_FragDepthEXT') || fs.includes('gl_FragDepthEXT') );
|
|
|
+ let addV300 = turnTo300 && matType != 'RawShaderMaterial'; // RawShaderMaterial直接material.glslVersion = '300 es' 以加在define之前
|
|
|
+ let change = (shader, shaderType)=>{
|
|
|
+ let newShader = shader;
|
|
|
+
|
|
|
+ if(turnTo300){ //非shaderMaterial需要手动改为300 es的写法
|
|
|
+ addV300 && (newShader = '#version 300 es \n' + newShader); //需要加 #version 300 es。 three.js自带的渲染会自动加所以不用
|
|
|
+ newShader = this.replaceAll(newShader, 'varying ', shaderType == 'vs' ? 'out ' : 'in ');
|
|
|
+ newShader = this.replaceAll(newShader, 'attribute ', 'in ');
|
|
|
+ if(shaderType == 'fs'){
|
|
|
+ newShader = this.replaceAll(newShader, 'gl_FragColor', 'fragColor');
|
|
|
+ newShader = newShader.replace('void main', 'out vec4 fragColor;\n void main' );//在void main前加入这个声明
|
|
|
+ }
|
|
|
+ newShader = this.replaceAll(newShader, 'gl_FragDepthEXT','gl_FragDepth');
|
|
|
+
|
|
|
+ newShader = this.replaceAll(newShader, 'texture2D','texture');
|
|
|
+ newShader = this.replaceAll(newShader, 'textureCube','texture');
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ newShader = newShader.replace('#extension GL_EXT_frag_depth : enable','');
|
|
|
+ newShader = this.replaceAll(newShader,'defined(GL_EXT_frag_depth) &&','');
|
|
|
+
|
|
|
+
|
|
|
+ otherReplaces.forEach(({oldStr,newStr})=>{
|
|
|
+ newShader = this.replaceAll(newShader, oldStr, newStr);
|
|
|
+ });
|
|
|
+
|
|
|
+ return newShader
|
|
|
+ };
|
|
|
+
|
|
|
+ vs = change(vs,'vs');
|
|
|
+ fs = change(fs,'fs');
|
|
|
+
|
|
|
+ //console.log('成功替换为webgl2' )
|
|
|
+ return {vs,fs}
|
|
|
+ },//three.js的shaderMaterial也有替换功能,搜 '#define gl_FragDepthEXT gl_FragDepth',
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //hsv感觉比hsl好一些,更能保持颜色本身不变。 色调(H),饱和度(S),明度(V/B)。
|
|
|
+
|
|
|
+
|
|
|
+ getHSV(color, prop={} ){
|
|
|
+ let c = new Color();
|
|
|
+ let hsv = c.set(color).getHSV();
|
|
|
+ if(prop.add){
|
|
|
+ for(let i in prop.add) hsv[i] += prop.add[i];
|
|
|
+ }else {
|
|
|
+ hsv = Object.assign(hsv, prop);
|
|
|
+ }
|
|
|
+ let {h, s, v} = hsv;
|
|
|
+ return c.setHSV(h, s, v) //setHSV(hsb.h, hsb.s, 100)
|
|
|
+ }
|
|
|
+
|
|
|
+ //let c = new THREE.Color().set(this.color).getHSL({ h: 0, s: 0, l: 0 })
|
|
|
+
|
|
|
+
|
|
|
};
|
|
|
|
|
|
Potree.Common = Common;
|
|
|
@@ -75718,8 +76014,7 @@ void main()
|
|
|
Potree.loadPanos( (data) => {
|
|
|
//console.log('loadPanos',dataset.sceneCode, dataset.id, data)
|
|
|
viewer.images360.addPanoData(data );
|
|
|
- viewer.images360.loadDone();
|
|
|
- viewer.scene.add360Images(viewer.images360);
|
|
|
+ viewer.images360.loadDone();
|
|
|
done();
|
|
|
});
|
|
|
}
|
|
|
@@ -96600,7 +96895,7 @@ ENDSEC
|
|
|
|
|
|
waitForLoad(){
|
|
|
viewer.waitForLoad(this, ()=>{//发送loading
|
|
|
- return this.depthTex && this.skyboxTex
|
|
|
+ return (!this.pointcloud.hasDepthTex || this.depthTex) && this.skyboxTex
|
|
|
});
|
|
|
}
|
|
|
|
|
|
@@ -98775,7 +99070,8 @@ ENDSEC
|
|
|
data.forEach((info)=>{
|
|
|
this.addPano(info);
|
|
|
|
|
|
- });
|
|
|
+ });
|
|
|
+
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -98796,7 +99092,7 @@ ENDSEC
|
|
|
viewer.hasNoPanoDataset = true;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+ viewer.scene.add360Images(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -139143,10 +139439,8 @@ ENDSEC
|
|
|
|
|
|
createHackMesh(){//为了防止无depthTex的全景在pick点云时画面中仅有一个材质时会黑屏,所以在镜头前再加一个mesh。具体bug表现见bug记录。
|
|
|
if(this.scene.pointclouds.every(e=>e.hasDepthTex) /* || viewer.images360.panos.length == 0 */)return
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- let mesh = new Mesh( new PlaneBufferGeometry(0.2,0.2) , new MeshBasicMaterial({color:"#F00",side:2/* ,depthTest:false */}));
|
|
|
+
|
|
|
+ let mesh = window.hackmesh = new Mesh( new PlaneBufferGeometry(1,1) , new MeshBasicMaterial({color:"#F00",side:2 /* ,depthTest:false */ }));
|
|
|
Potree.Utils.updateVisible(mesh,'show',false);
|
|
|
|
|
|
this.images360.node.add(mesh);
|
|
|
@@ -139156,6 +139450,7 @@ ENDSEC
|
|
|
let dir = this.mainViewport.view.direction;
|
|
|
let radius = this.images360.cube.scale.length();
|
|
|
mesh.position.copy(this.mainViewport.view.position).add(dir.multiplyScalar(radius));//放置skybox之外
|
|
|
+ mesh.quaternion.copy(this.mainViewport.camera.quaternion);
|
|
|
};
|
|
|
|
|
|
|