|
@@ -53395,35 +53395,36 @@
|
|
|
|
|
|
,
|
|
|
|
|
|
- CloneObject : function(copyObj, result, isSimpleCopy, simpleCopyList=[]) {
|
|
|
+ CloneObject : function (copyObj, isSimpleCopy, simpleCopyList = [], judgeSimpleCopyFun) {
|
|
|
//isSimpleCopy 只复制最外层
|
|
|
//复制json result的可能:普通数字或字符串、普通数组、复杂对象
|
|
|
-
|
|
|
- simpleCopyList.push(Object3D); //遇到simpleCopyList中的类直接使用不拷贝
|
|
|
+
|
|
|
+ simpleCopyList.includes(Object3D) || simpleCopyList.push(Object3D); //遇到simpleCopyList中的类直接使用不拷贝
|
|
|
+ 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 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();
|
|
@@ -53443,7 +53444,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 );
|
|
|
}
|
|
|
|
|
|
|
|
@@ -53618,28 +53619,38 @@
|
|
|
}
|
|
|
},
|
|
|
|
|
|
-
|
|
|
-
|
|
|
- getBestCount : function(name, minCount=1,maxCount=6, durBound1 = 1.2, durBound2 = 10, ifLog){
|
|
|
-
|
|
|
-
|
|
|
- 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; // ?
|
|
|
- }
|
|
|
-
|
|
|
- //主要在手机端有效果。
|
|
|
- return count
|
|
|
- },
|
|
|
+
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ })(),
|
|
|
|
|
|
|
|
|
|
|
@@ -60785,7 +60796,7 @@
|
|
|
|
|
|
let gl = ftCanvas.getContext('webgl') || ftCanvas.getContext('experimental-webgl');
|
|
|
if (gl === null){
|
|
|
- return null;
|
|
|
+ return {};
|
|
|
}
|
|
|
|
|
|
// -- code taken from THREE.WebGLRenderer --
|
|
@@ -62816,7 +62827,10 @@ void main() {
|
|
|
// vOpacity = clamp(vOpacity, 0.001, 1.0);
|
|
|
}
|
|
|
|
|
|
- vOpacity *= max(0.02, pow((1.0 - normalZ),5.0));//垂直朝相机时降低透明度
|
|
|
+ vOpacity *= max(0.05, pow((1.0 - normalZ),5.0));//垂直朝相机时降低透明度
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
// POINT SIZE
|
|
|
float pointSize = getPointSize();
|
|
@@ -70473,7 +70487,7 @@ void main()
|
|
|
|
|
|
moveLine: function (line, posArr) {
|
|
|
if(posArr.length == 0)return
|
|
|
- posArr = dealPosArr(posArr);
|
|
|
+ if(!line.uncontinuous)posArr = dealPosArr(posArr);
|
|
|
let position = [];
|
|
|
posArr.forEach(e=>position.push(e.x,e.y,e.z));
|
|
|
line.geometry.setAttribute('position', new Float32BufferAttribute(/* new Float32Array( */position/* ) */, 3));
|
|
@@ -70530,7 +70544,7 @@ void main()
|
|
|
var matLine = o.mat || this.createFatLineMat(o);
|
|
|
var line = new Line2( geometry, matLine );
|
|
|
//line.computeLineDistances();
|
|
|
-
|
|
|
+ line.uncontinuous = o.uncontinuous; //线不连续,由线段组成
|
|
|
line.scale.set( 1, 1, 1 );
|
|
|
line.renderOrder = 2;
|
|
|
|
|
@@ -70545,7 +70559,7 @@ void main()
|
|
|
moveFatLine: function(line, posArr){
|
|
|
var geometry = line.geometry;
|
|
|
var positions = [];
|
|
|
- posArr = dealPosArr(posArr);
|
|
|
+ line.uncontinuous || (posArr = dealPosArr(posArr));
|
|
|
posArr.forEach(e=>{positions.push(...e.toArray());});
|
|
|
|
|
|
|
|
@@ -73619,6 +73633,7 @@ void main()
|
|
|
if(MathUtils.isPowerOfTwo(map.image.width ) && MathUtils.isPowerOfTwo(map.image.height ))return
|
|
|
map.wrapS = map.wrapT = ClampToEdgeWrapping; //原默认 RepeatWrapping
|
|
|
map.minFilter = LinearFilter; // or THREE.NearestFilter 原默认 LinearMipmapLinearFilter
|
|
|
+ map.generateMipmaps = false;
|
|
|
map.needsUpdate = true;
|
|
|
};
|
|
|
|
|
@@ -74775,7 +74790,7 @@ void main()
|
|
|
}
|
|
|
let memoryRatio = browser.isMobile() ? 2 : 5;
|
|
|
//改成navvis的,使用pointBudget,否则四屏点云闪烁。 (似乎要比updateVisiblede的node时限制要宽些,作为缓存继续存着。否则会闪烁)
|
|
|
- let max = viewer.viewports.length * memoryRatio * Potree.pointBudget;
|
|
|
+ let max = MathUtils.clamp( viewer.viewports.length * memoryRatio * Potree.pointBudget, 1e6, 40e6);
|
|
|
|
|
|
for (; this.numPoints > max; ) {
|
|
|
var node = this.getLRUItem();
|
|
@@ -75217,7 +75232,7 @@ void main()
|
|
|
panosLoaded ++;
|
|
|
if(panosLoaded == datasetLength){
|
|
|
|
|
|
- Potree.loadImgVersion((e)=>{
|
|
|
+ Potree.loadImgVersion((e={})=>{
|
|
|
Potree.settings.panoVersion = e.imgVersion;//全景图被替换后
|
|
|
panosLoadDone();
|
|
|
});
|
|
@@ -76072,7 +76087,7 @@ void main()
|
|
|
magnifier:{
|
|
|
maxLevelPercent: 1,
|
|
|
pointBudget : 8*1000*1000,
|
|
|
- },
|
|
|
+ },
|
|
|
panorama:{//显示全景时的漫游。因为点只能显示1个像素的大小,所以必须很密集,但又要限制点的数量
|
|
|
maxLevelPercent: 0.6,
|
|
|
pointBudget : /* 4*1000*1000// */browser.isMobile() ? 0.1*1000*1000 : 0.4*1000*1000, //点云总最大数
|
|
@@ -76943,7 +76958,7 @@ void main()
|
|
|
}
|
|
|
this.changePointOpacity();
|
|
|
//}
|
|
|
- viewer.dispatchEvent('content_changed');
|
|
|
+ viewer.dealBeforeRender || viewer.dispatchEvent('content_changed');
|
|
|
}
|
|
|
|
|
|
//预测可能的nodeMaxLevel:
|
|
@@ -77299,6 +77314,9 @@ void main()
|
|
|
// 设置点大小
|
|
|
changePointSize(num, sizeFitToLevel) {
|
|
|
let size, nodeMaxLevel;
|
|
|
+
|
|
|
+ let dontRender = viewer.dealBeforeRender;
|
|
|
+
|
|
|
if(this.material.pointSizeType != PointSizeType.ATTENUATED){
|
|
|
num && (size = num / Potree.config.material.realPointSize / 1.3);
|
|
|
}else {
|
|
@@ -77349,20 +77367,22 @@ void main()
|
|
|
this.material.size = size;
|
|
|
}
|
|
|
}
|
|
|
- viewer.dispatchEvent('content_changed');
|
|
|
+ dontRender || viewer.dispatchEvent('content_changed');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 设置点透明度
|
|
|
- changePointOpacity(num, canMoreThanOne) {
|
|
|
+ changePointOpacity(num, canMoreThanOne ) {
|
|
|
//num:0-1 navvis用的是亮度
|
|
|
if (num == void 0) {
|
|
|
num = this.temp.pointOpacity;
|
|
|
} else {
|
|
|
this.temp.pointOpacity = num;
|
|
|
}
|
|
|
+ let dontRender = viewer.dealBeforeRender; //在执行beforeRender时更改的话不要发送content_changed 尤其分屏
|
|
|
+
|
|
|
|
|
|
if(Potree.settings.notAdditiveBlending){
|
|
|
return this.material.opacity = num
|
|
@@ -77409,8 +77429,7 @@ void main()
|
|
|
this.material.opacity = opacity;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- viewer.dispatchEvent('content_changed');
|
|
|
+ dontRender || viewer.dispatchEvent('content_changed');
|
|
|
}
|
|
|
|
|
|
|
|
@@ -96093,7 +96112,7 @@ void main()
|
|
|
}
|
|
|
//Potree.settings.panoVersion = 4
|
|
|
d += g + (Potree.settings.panoVersion ? 'version='+Potree.settings.panoVersion : 'time='+o.pano.pointcloud.timeStamp ); //加后缀
|
|
|
-
|
|
|
+
|
|
|
return d;
|
|
|
|
|
|
|
|
@@ -97306,27 +97325,27 @@ void main()
|
|
|
E = tileSize / panoSize * size, // tile在renderTarget上渲染出的宽度
|
|
|
b = C / panoSize * size, // tile在renderTarget上渲染的startX
|
|
|
w = I / panoSize * size; // tile在renderTarget上渲染的startY
|
|
|
- collection[tileSize] || (collection[tileSize] = this.initSizedTexture2D(tileSize, ClampToEdgeWrapping));
|
|
|
-
|
|
|
|
|
|
if(panoSize > this.qualityManager.maxRenderTargetSize ){ //4096 改
|
|
|
- var tex = this.initSizedTexture2D(tileSize, ClampToEdgeWrapping);
|
|
|
- var loaded = this.viewer.images360.isHighMapLoaded(info.cubeFace, tileX,tileY);
|
|
|
- }else {
|
|
|
- var tex = collection[tileSize];
|
|
|
- }
|
|
|
- this.uploadTexture2D(img, tex, 0, 0, tileSize, tileSize);//只替换tex对应的img,不新建
|
|
|
-
|
|
|
- if(panoSize > this.qualityManager.maxRenderTargetSize){
|
|
|
- loaded || this.viewer.images360.updateHighMap(tex, info.cubeFace, tileX,tileY);
|
|
|
+ /* var tex = this.initSizedTexture2D(tileSize, THREE.ClampToEdgeWrapping);
|
|
|
+ var loaded = this.viewer.images360.isHighMapLoaded(info.cubeFace, tileX,tileY) */
|
|
|
+ this.viewer.images360.getHighImage(img, info.cubeFace, tileX, tileY);
|
|
|
+ }else {
|
|
|
+ collection[tileSize] || (collection[tileSize] = this.initSizedTexture2D(tileSize, ClampToEdgeWrapping));
|
|
|
+ var tex = collection[tileSize];
|
|
|
|
|
|
- }else {
|
|
|
- if (1 === overlayStyle || 2 === overlayStyle) {
|
|
|
- var T = 1 === overlayStyle ? this.overlayTilesBasic : this.overlayTilesEnhanced;
|
|
|
- this.renderToCubeMap(tex, renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace);
|
|
|
- this.renderToCubeMap(T[panoSize], renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace, NormalBlending, !0, .5);
|
|
|
- } else {
|
|
|
- this.renderToCubeMap(tex, renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace);
|
|
|
+ this.uploadTexture2D(img, tex, 0, 0, tileSize, tileSize);//只替换tex对应的img,不新建
|
|
|
+
|
|
|
+ if(panoSize > this.qualityManager.maxRenderTargetSize){
|
|
|
+ loaded || this.viewer.images360.updateHighMap(tex, info.cubeFace, tileX,tileY);
|
|
|
+ }else {
|
|
|
+ if (1 === overlayStyle || 2 === overlayStyle) {
|
|
|
+ var T = 1 === overlayStyle ? this.overlayTilesBasic : this.overlayTilesEnhanced;
|
|
|
+ this.renderToCubeMap(tex, renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace);
|
|
|
+ this.renderToCubeMap(T[panoSize], renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace, NormalBlending, !0, .5);
|
|
|
+ } else {
|
|
|
+ this.renderToCubeMap(tex, renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
done();
|
|
@@ -98954,7 +98973,7 @@ void main()
|
|
|
|
|
|
|
|
|
|
|
|
- isNeighbour(pano0, pano1, dontCompute, onlyUseTex, computeDirFirst){//是否之间没有遮挡(在加载visibles之前,自己算) 最好pano0是currentPano
|
|
|
+ isNeighbour(pano0, pano1, {dontCompute, onlyUseTex, computeDirFirst, computeTwoDir}={}){//是否之间没有遮挡(在加载visibles之前,自己算) 最好pano0是currentPano
|
|
|
|
|
|
if(!pano0 || !pano1 )return
|
|
|
|
|
@@ -98999,7 +99018,7 @@ void main()
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- if( map0[pano1.id] == void 0 && !ifNeighbour ) {//主方向为空且不为邻居
|
|
|
+ if(!ifNeighbour && (map0[pano1.id] == void 0 || (computeTwoDir && map1[pano0.id] == void 0))) {//主方向为空且不为邻居
|
|
|
let simpleJudge = pano0.position.distanceToSquared(pano1.position) > 300; //在远处去掉对floorPosition的判断
|
|
|
if(pano0.depthTex || pano1.depthTex){
|
|
|
|
|
@@ -99013,7 +99032,7 @@ void main()
|
|
|
map0[pano1.id] = !!is;
|
|
|
}
|
|
|
|
|
|
- if( ifNeighbour == void 0 && /* map1[pano0.id] == void 0 && */ pano1.depthTex){ //若正向为false,反向暂且不算,等到pano0为主时再算
|
|
|
+ if(map1[pano0.id] == void 0 && pano1.depthTex){
|
|
|
let is = getNeighbour(pano1, pano0, !ifNeighbour, simpleJudge);
|
|
|
if(is){
|
|
|
ifNeighbour = true;
|
|
@@ -99222,8 +99241,7 @@ void main()
|
|
|
}
|
|
|
} */
|
|
|
// 不会再changeTex了
|
|
|
-
|
|
|
- let isNeighbour = this.isNeighbour(this.currentPano, pano, false, true);
|
|
|
+ let isNeighbour = this.isNeighbour(this.currentPano, pano, {onlyUseTex:true});
|
|
|
|
|
|
if(isNeighbour || pano.noNeighbour && disSquareMap.get(pano) < 200){//在靠近孤立点时可以通行。但是不好把握这个距离,太远的话很多地方都会不小心到孤立点,太近的话可能永远到不了。
|
|
|
return true
|
|
@@ -99248,7 +99266,7 @@ void main()
|
|
|
Images360.scoreFunctions[o]( this.position, direction, true),
|
|
|
|
|
|
(pano)=>{
|
|
|
- let neighbour = this.isNeighbour(this.currentPano, pano, true, true); //不计算的
|
|
|
+ let neighbour = this.isNeighbour(this.currentPano, pano, {dontCompute:true, isNeighbour:true}); //不计算的
|
|
|
|
|
|
return neighbour ? directionFactor : 0;
|
|
|
} ,
|
|
@@ -99771,6 +99789,7 @@ void main()
|
|
|
|
|
|
var geo = new PlaneGeometry(1, 1, 1, 1);
|
|
|
var cube = new Object3D;
|
|
|
+ cube.tiles = [];
|
|
|
for(var cubeIndex=0; cubeIndex<6; cubeIndex++){
|
|
|
var face = new Object3D;
|
|
|
for(var i=0;i<8;i++){
|
|
@@ -99791,6 +99810,11 @@ void main()
|
|
|
}
|
|
|
|
|
|
tile.visible = false;
|
|
|
+ tile.tileX = i;
|
|
|
+ tile.tileY = j;
|
|
|
+ tile.cubeFace = cubeIndex;
|
|
|
+ //tile.renderOrder = RenderOrder.highTileCube
|
|
|
+ cube.tiles.push(tile);
|
|
|
face.add(tile);
|
|
|
}
|
|
|
}
|
|
@@ -99823,6 +99847,7 @@ void main()
|
|
|
|
|
|
}
|
|
|
face.scale.set(1,-1,1);
|
|
|
+ face.cubeFace = cubeIndex;
|
|
|
cube.add(face);
|
|
|
}
|
|
|
cube.name = 'highMapCube';
|
|
@@ -99838,6 +99863,27 @@ void main()
|
|
|
Potree.Utils.setObjectLayers(this.highMapCube, 'sceneObjects'/* 'skybox' */); //因它的深度是错误的,故不在skybox层渲染,影响edlRT, 而在renderOverlay时渲染覆盖。
|
|
|
//console.warn('addHighMapCube')
|
|
|
|
|
|
+
|
|
|
+ viewer.addEventListener('update',()=>{
|
|
|
+ if (this.highMapCube.visibleTiles) {
|
|
|
+ this.updateTiles(); //逐步将visibleTiles加载完
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ viewer.addEventListener('camera_changed',(e)=>{
|
|
|
+ if(e.viewport == viewer.mainViewport){
|
|
|
+ //重新获取visibleTiles
|
|
|
+ Common$1.intervalTool.isWaiting(
|
|
|
+ 'update4kTiles',
|
|
|
+ () => {
|
|
|
+ console.log('update4kTiles');
|
|
|
+ let vectorForward = this.getDirection();
|
|
|
+ this.updateTiles(vectorForward);
|
|
|
+ },
|
|
|
+ 500
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
}
|
|
@@ -99849,9 +99895,93 @@ void main()
|
|
|
}
|
|
|
|
|
|
|
|
|
- updateHighMap(tex, cubeFace, tileX, tileY){
|
|
|
+ updateTiles(direction) {
|
|
|
+ if (!this.highMapCube || !this.highMapCube.visible) return
|
|
|
+
|
|
|
+ if (this.highMapCube.tiles.filter(e => e.image).length <= 10) return //加载的太少了
|
|
|
+ //performance.mark('updateTiles-start')
|
|
|
+
|
|
|
+ if (direction) {
|
|
|
+ let camera = viewer.mainViewport.camera;
|
|
|
+ let hfov = cameraLight.getHFOVForCamera(camera, true) / 2;
|
|
|
+ let vfov = MathUtils.degToRad(camera.fov) / 2;
|
|
|
+ /* let hcos = Math.cos(hfov / 2)
|
|
|
+ let vcos = Math.cos(vfov / 2) */
|
|
|
+ let list = this.highMapCube.tiles;
|
|
|
+ list.forEach(e => {
|
|
|
+ //屏幕外的不显示
|
|
|
+ let pos = e.getWorldPosition(new Vector3());
|
|
|
+ let dir = new Vector3().subVectors(pos, this.highMapCube.position).normalize();
|
|
|
+
|
|
|
+ let hcos_ = dir.clone().setY(direction.y).normalize().dot(direction); //在direction的斜面上水平角度差
|
|
|
+ let hRad = Math.acos(hcos_);
|
|
|
+ let vRad = -200;
|
|
|
+ if (hRad > hfov + 0.1) {
|
|
|
+ e.score = -100;
|
|
|
+ } else {
|
|
|
+ vRad = Math.abs(Math.acos(dir.y) - Math.acos(direction.y));
|
|
|
+ if (vRad > vfov + 0.1) {
|
|
|
+ e.score = -100;
|
|
|
+ } else {
|
|
|
+ e.score = -(hRad / hfov + vRad / vfov);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ e.scores = hRad.toFixed(3) + ', ' + vRad.toFixed(3);
|
|
|
+
|
|
|
+ if (e.score == -100) {
|
|
|
+ this.resetTile(e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.highMapCube.visibleTiles = list.filter(e => e.score > -100);
|
|
|
+ //list.forEach(e=>e.scoreLabel.setText(e.scores))
|
|
|
+ }
|
|
|
+
|
|
|
+ let needRecover = this.highMapCube.visibleTiles.filter(e => !e.material.map);
|
|
|
+
|
|
|
+ if (needRecover.length) {
|
|
|
+ let maxCount = Common$1.getBestCount( '4kmaxTileRecover', 0, 2, 1.5, 6, false, 2 );
|
|
|
+ let count = 0;
|
|
|
+ console.log(maxCount);
|
|
|
+ needRecover.forEach((e, i) => {
|
|
|
+ //只更新若干个,因为太耗时了, 其余的等下帧更新
|
|
|
+ if (count >= maxCount) return
|
|
|
+ let r = this.recoverTile(e);
|
|
|
+ if (r) count++;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ getHighImage(image, cubeFace, tileX, tileY) {
|
|
|
+ let tile = this.highMapCube.children[cubeFace].children[tileX * 8 + tileY];
|
|
|
+ tile.image = image; //先记录下来
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ updateHighMap(image, cubeFace, tileX, tileY){
|
|
|
//console.warn('updateHighMap')
|
|
|
var tile = this.highMapCube.children[cubeFace].children[tileX*8+tileY];
|
|
|
+ if (image) tile.image = image; //先记录下来
|
|
|
+ if(tile.material.map)return
|
|
|
+
|
|
|
+ if (this.highMapCube.visibleTiles && !this.highMapCube.visibleTiles.includes(tile) /* this.highMapCube.texLoadedCount >= this.getMaxTileCount() */) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ //简易创建贴图
|
|
|
+ /* var tex = this.$app.core.get('SceneRenderer').initSizedTexture2D(512, THREE.ClampToEdgeWrapping)
|
|
|
+ //var loaded = this.$app.core.get('Player').model.isHighMapLoaded(tile.cubeFace, tile.tileX, tile.tileY)
|
|
|
+ this.$app.core.get('SceneRenderer').uploadTexture2D(image, tex, 0, 0, 512, 512) //只替换tex对应的img,不新建
|
|
|
+ */
|
|
|
+ var tex = new Texture();
|
|
|
+ tex.image = image;
|
|
|
+ tex.flipY = false;
|
|
|
+ tex.wrapS = tex.wrapT = ClampToEdgeWrapping;
|
|
|
+ tex.generateMipmaps = false;
|
|
|
+ tex.minFilter = LinearFilter;
|
|
|
+ tex.needsUpdate = true;
|
|
|
|
|
|
tile.material.map = tex;
|
|
|
|
|
@@ -99863,31 +99993,58 @@ void main()
|
|
|
tile.material.needsUpdate = true; //发现每次开始放大但还未放大到4k时也会把之前加载过的4k加载
|
|
|
}
|
|
|
|
|
|
+ recoverTile(tile) {
|
|
|
+ if (tile.material.map) return
|
|
|
+ if (tile.image) {
|
|
|
+ this.updateHighMap(tile.image, tile.cubeFace, tile.tileX, tile.tileY);
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ //console.log('no image')
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
+ resetTile(tile, kill) {
|
|
|
+ if (kill) {
|
|
|
+ //完全消灭
|
|
|
+ tile.image = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ let map = tile.material.map;
|
|
|
+ if (map) {
|
|
|
+ map.dispose(); //这句执行了以后,h.__webglTexture一直就是undefined
|
|
|
+ map.loaded = !1;
|
|
|
+ map.version = 0;
|
|
|
+
|
|
|
+ //保底再执行一下这个,类似app.sceneRenderer.deallocateCubeTexture(tile.material.map)
|
|
|
+ var h = viewer.renderer.properties.get(map);
|
|
|
+ //console.log('__webglTexture',!!h.__webglTexture)
|
|
|
+ viewer.renderer.getContext().deleteTexture(h.__webglTexture);
|
|
|
+
|
|
|
+ tile.material.map = null;
|
|
|
+
|
|
|
+
|
|
|
+ tile.material.needsUpdate = true;
|
|
|
+ tile.visible = false;
|
|
|
+
|
|
|
+ //this.highMapCube.texLoadedCount --
|
|
|
+ //console.log('resetTile'/* , tile.cubeFace, tile.tileX, tile.tileY */)
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- resetHighMap(){
|
|
|
|
|
|
- if(!this.highMapCube) return
|
|
|
- //console.warn('resetHighMap')
|
|
|
- this.highMapCube.children.forEach(e=>e.children.forEach(tile=>{
|
|
|
- if(tile.material.map){
|
|
|
- tile.material.map.dispose(); //这句其实无效。本来可以使用three自带的deallocateTexture(texture),但因为创建的方式不是普通的new Texture,所以并没有onTextureDispose的侦听,故要自己写
|
|
|
- tile.material.map.loaded = !1;
|
|
|
- tile.material.map.version = 0;
|
|
|
-
|
|
|
- //这两句才是真正释放贴图资源的 ,类似app.sceneRenderer.deallocateCubeTexture(tile.material.map)
|
|
|
- var h = viewer.renderer.properties.get(tile.material.map);
|
|
|
- viewer.renderer.getContext().deleteTexture(h.__webglTexture);
|
|
|
- //类似app.sceneRenderer.deallocateCubeTexture(tile.material.map)
|
|
|
-
|
|
|
- tile.material.map = null;
|
|
|
- /* tile.material.opacity = 0.4;
|
|
|
- tile.material.transparent = true */
|
|
|
- tile.material.needsUpdate = true;
|
|
|
- tile.visible = false;
|
|
|
- }
|
|
|
- }));
|
|
|
+
|
|
|
+
|
|
|
+ resetHighMap() {
|
|
|
+ if (!this.highMapCube) return
|
|
|
+ this.highMapCube.children.forEach(e =>
|
|
|
+ e.children.forEach(tile => {
|
|
|
+ this.resetTile(tile, true);
|
|
|
+ })
|
|
|
+ );
|
|
|
+ //this.highMapCube.texLoadedCount = 0
|
|
|
+ this.highMapCube.visibleTiles = null;
|
|
|
this.hideHighMap();
|
|
|
+ //console.log('resetHighMap')
|
|
|
}
|
|
|
|
|
|
setHighMap(pano){
|
|
@@ -100082,10 +100239,13 @@ void main()
|
|
|
|
|
|
for(let a=0, b=g.length; a<b; a++){
|
|
|
let item = g[a];
|
|
|
- if(this.isNeighbour(pano, item.item, true) != void 0) continue
|
|
|
+ if(item.item == pano)continue
|
|
|
+ if(this.isNeighbour(pano,item.item,{dontCompute:true}) || this.neighbourMap[pano.id][item.item.id]!= void 0 && this.neighbourMap[item.item.id][pano.id]!= void 0)continue //为true或两个方向都算了的
|
|
|
|
|
|
+ //console.log('check isNeighbour', pano.id, item.item.id)
|
|
|
+
|
|
|
let byCloud = !pano.pointcloud.hasDepthTex;
|
|
|
- let result = this.isNeighbour(pano, item.item, false, !byCloud, true);//计算
|
|
|
+ let result = this.isNeighbour(pano, item.item, {onlyUseTex: !byCloud, computeDirFirst:true, computeTwoDir:true});//计算
|
|
|
|
|
|
if(result != void 0){//计算了
|
|
|
//console.log('提前计算neighbor', pano.id, item.item.id)
|
|
@@ -100880,9 +101040,9 @@ void main()
|
|
|
});
|
|
|
|
|
|
//viewer.addEventListener("global_mousemove", this.updateWhenAtViewer.bind(this)) //鼠标移动时reticule也动,所以直接就needRender
|
|
|
- viewer.reticule.addEventListener('update',(e)=>{
|
|
|
- if(this.attachedToViewer)this.needRender = true;
|
|
|
- });
|
|
|
+ /* viewer.reticule.addEventListener('update',(e)=>{
|
|
|
+ if(this.attachedToViewer)this.needRender = true
|
|
|
+ }) */
|
|
|
|
|
|
|
|
|
viewer.scene.addEventListener("360_images_added", this.addPanos.bind(this));
|
|
@@ -102710,7 +102870,7 @@ ENDSEC
|
|
|
positions.forEach(e=>e.z *= -1); //因为得到的rotation是camera的,作用在物体上要反向,所以这里反向一下
|
|
|
|
|
|
//geometry.computeBoundingSphere();//?
|
|
|
- const line = LineDraw.createFatLine( positions, {material:getLineMat('frustum')});
|
|
|
+ const line = LineDraw.createFatLine( positions, {mat:getLineMat('frustum')});
|
|
|
|
|
|
//line.scale.set(20, 20, 20);
|
|
|
line.visible = false;
|
|
@@ -111345,6 +111505,9 @@ ENDSEC
|
|
|
viewer.setLimitFar(false);
|
|
|
viewer.mapViewer.attachToMainViewer(true,'split4Screens','dontSet');
|
|
|
|
|
|
+ viewer.renderer.clear(); //clear back的viewport左边的1px宽的部分,因setScissor的bug
|
|
|
+
|
|
|
+
|
|
|
let viewports = this.splitStart(viewportProps);
|
|
|
|
|
|
//覆盖在map上、点云等其他物体之下的一层背景
|
|
@@ -111404,7 +111567,9 @@ ENDSEC
|
|
|
} */
|
|
|
});
|
|
|
|
|
|
- let beforeRender = function(){
|
|
|
+ let beforeRender = function(){
|
|
|
+ viewer.dealBeforeRender = true; //使不全部渲染
|
|
|
+
|
|
|
viewer.scene.pointclouds.forEach(e=>{
|
|
|
if(this.name == "MainView"){
|
|
|
e.material.activeAttributeName = matBefore.colorType; // 'rgba'
|
|
@@ -111432,11 +111597,9 @@ ENDSEC
|
|
|
}else {
|
|
|
Potree.Utils.updateVisible(pano.marker, 'showOnMap', false, 1, 'cancel' );
|
|
|
}
|
|
|
- });
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- });
|
|
|
+ });
|
|
|
+ });
|
|
|
+ viewer.dealBeforeRender = false;
|
|
|
};
|
|
|
viewports.forEach(viewport=>{viewport.beforeRender = beforeRender;});
|
|
|
|
|
@@ -121956,7 +122119,8 @@ ENDSEC
|
|
|
|
|
|
this.hidden = !0;
|
|
|
transitions.start(lerp.property(this.material , "opacity", 0, ()=>{//progress
|
|
|
- viewer.dispatchEvent('content_changed');
|
|
|
+ this.dispatchEvent({type:'update' });
|
|
|
+ //viewer.dispatchEvent('content_changed')
|
|
|
}), duration,()=>{//done
|
|
|
this.dispatchEvent({type:'update', visible:false});
|
|
|
});
|
|
@@ -121977,7 +122141,9 @@ ENDSEC
|
|
|
|
|
|
if(this.material.opacity <= 0){
|
|
|
transitions.start(lerp.property(this.material, "opacity", defaultOpacity, ()=>{//progress
|
|
|
- viewer.dispatchEvent('content_changed');
|
|
|
+ this.dispatchEvent({type:'update' });
|
|
|
+
|
|
|
+ //viewer.dispatchEvent('content_changed')
|
|
|
}), duration,()=>{//done
|
|
|
this.dispatchEvent({type:'update', visible:false});
|
|
|
});
|
|
@@ -128716,7 +128882,13 @@ ENDSEC
|
|
|
//为了防止chrome出现报错 The source image could not be decoded. 导致reject,重新写贴图加载方式: xzw
|
|
|
|
|
|
parser.textureLoader.load(sourceURI, (tex)=>{
|
|
|
- tex.minFilter = THREE.LinearMipmapLinearFilter; //原本:NearestMipMapNearestFilter 闪烁
|
|
|
+
|
|
|
+ THREE.LinearMipmapLinearFilter; //原本:NearestMipMapNearestFilter 闪烁
|
|
|
+ //有一个block文件离远了有裂缝,只能使用LinearFilter,但是这样似乎更卡,且锯齿
|
|
|
+ /* tex.minFilter = THREE.LinearFilter
|
|
|
+ tex.generateMipmaps = false */
|
|
|
+
|
|
|
+
|
|
|
|
|
|
Potree.Utils.makeTexDontResize(tex);
|
|
|
//console.log(tex.image.width, tex.image.height)
|
|
@@ -147924,11 +148096,13 @@ ENDSEC
|
|
|
|
|
|
if(!ifForce) ifForce = tileset.nextForceUpdate;
|
|
|
tileset.nextForceUpdate = false;
|
|
|
- if(tileset.needRenderNext){
|
|
|
+ if(tileset.needRenderNext){//必须在下一帧渲染刷新否则无法显示
|
|
|
viewer.dispatchEvent('content_changed');
|
|
|
- }
|
|
|
-
|
|
|
+ }
|
|
|
tileset.needRenderNext = ifForce;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
if (tileset && (timer >= UPDATE_INTERVAL || ifForce)) {
|
|
|
if (!lastRootTransform.equals(root.matrixWorld)) {
|
|
@@ -151064,10 +151238,10 @@ ENDSEC
|
|
|
|
|
|
|
|
|
Potree.isIframeChild = window.parent!=window; //子页面
|
|
|
- if(Potree.isIframeChild){
|
|
|
- let rootWin = Common$1.getRootWindow();
|
|
|
- rootWin && rootWin.viewer.dispatchEvent({type:'createIframe', window}); //给祖先页面发送信息,得不到可能跨域了或无viewer
|
|
|
- }
|
|
|
+ /* if(Potree.isIframeChild){
|
|
|
+ let rootWin = Common.getRootWindow()
|
|
|
+ rootWin && rootWin.viewer.dispatchEvent({type:'createIframe', window}) //给祖先页面发送信息,得不到可能跨域了或无viewer
|
|
|
+ } */
|
|
|
/* window.addEventListener('focus',()=>{
|
|
|
console.log('focus',window.winIndex)
|
|
|
})
|
|
@@ -151637,13 +151811,21 @@ ENDSEC
|
|
|
}
|
|
|
|
|
|
|
|
|
- this.reticule.addEventListener('update',(e)=>{
|
|
|
- this.needRender = true;
|
|
|
- if(this.mapViewer && this.mapViewer.attachedToViewer)this.mapViewer.needRender = true; //分屏时mapViewer也有reticule
|
|
|
+ /* this.reticule.addEventListener('update',(e)=>{
|
|
|
+ this.needRender = true
|
|
|
+ if(this.mapViewer && this.mapViewer.attachedToViewer)this.mapViewer.needRender = true //分屏时mapViewer也有reticule
|
|
|
+ }) */
|
|
|
+
|
|
|
+ this.reticule.addEventListener('update',(e)=>{
|
|
|
+ this.reticule.hoverViewport && (this.reticule.hoverViewport.needRender = true);
|
|
|
+ this.lazyRenderViewports();
|
|
|
+ if(this.mapViewer && this.mapViewer.attachedToViewer &&
|
|
|
+ (this.mapViewer.viewports[0].needRender || this.needRender ) ) this.mapViewer.needRender = true; //分屏时mapViewer也有reticule
|
|
|
});
|
|
|
|
|
|
+
|
|
|
this.addEventListener('pointcloud_changed',(e)=>{
|
|
|
- this.needRender = true;
|
|
|
+ this.lazyRenderViewports();
|
|
|
});
|
|
|
|
|
|
|
|
@@ -151756,17 +151938,15 @@ ENDSEC
|
|
|
}
|
|
|
|
|
|
|
|
|
- if(!Potree.isIframeChild){
|
|
|
+ /* if(!Potree.isIframeChild){
|
|
|
window.winIndex = 0;
|
|
|
let index = 1;
|
|
|
this.addEventListener('createIframe',(e)=>{//创建了子页面
|
|
|
let child = e.window;
|
|
|
- child.winIndex = index ++;
|
|
|
-
|
|
|
-
|
|
|
- });
|
|
|
+ child.winIndex = index ++;
|
|
|
+ })
|
|
|
//不知道删除iframe时是否那些模型还在内存里,需要释放吗? 如果要需要加一个事件
|
|
|
- }
|
|
|
+ } */
|
|
|
|
|
|
|
|
|
|
|
@@ -151810,6 +151990,42 @@ ENDSEC
|
|
|
|
|
|
}
|
|
|
|
|
|
+ lazyRenderViewports(updateCount){
|
|
|
+ //本来要写this.needRender = true的, 但在分四个屏时防止太卡而排队render
|
|
|
+ let viewports = this.viewports;
|
|
|
+ if(viewports.length == 1 || this.needRender){
|
|
|
+ return this.needRender = true
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ const maxWaitTime = 200;
|
|
|
+
|
|
|
+ let now = Date.now();
|
|
|
+
|
|
|
+ let count = 1;
|
|
|
+
|
|
|
+ viewports.forEach(e=>{
|
|
|
+ if(now - e.lastRenderTime > maxWaitTime){
|
|
|
+ e.needRender = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ let useCount = viewports.filter(e=>e.needRender).length;
|
|
|
+ //console.log('useCount', useCount)
|
|
|
+
|
|
|
+ let list = viewports.filter(e=>!e.needRender).sort((a,b)=>a.lastRenderTime - b.lastRenderTime);
|
|
|
+
|
|
|
+ if(useCount < count){
|
|
|
+ list.slice(0, count - useCount).forEach(e=>{
|
|
|
+ e.needRender = true;
|
|
|
+ });
|
|
|
+ }else if(list[0] && now - list[0].lastRenderTime > maxWaitTime){
|
|
|
+ list[0].needRender = true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
@@ -154033,13 +154249,20 @@ ENDSEC
|
|
|
}
|
|
|
if(width == 0 || height == 0)return
|
|
|
|
|
|
- let scissorTest = view.width<1 || view.height<1;
|
|
|
+ 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;
|
|
|
this.renderer.setRenderTarget(params_.target);
|
|
|
- }else {
|
|
|
+ }else {
|
|
|
+ /* if(viewports.length == 1 && left == 0 && bottom == 0){
|
|
|
+ left = 1 , width-=1 //这种情况下渲染也会有问题,只有鼠标的地方刷新
|
|
|
+ } */
|
|
|
+ if(scissorTest && left == 0 && bottom == 0){
|
|
|
+ left = 1 , width-=1;
|
|
|
+ }
|
|
|
+
|
|
|
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时开启会只有鼠标的地方刷新,很奇怪
|
|
@@ -154053,8 +154276,8 @@ ENDSEC
|
|
|
|
|
|
viewer.dispatchEvent({type: "render.begin", viewer: viewer, viewport:view, params });
|
|
|
|
|
|
-
|
|
|
- view.beforeRender && view.beforeRender();
|
|
|
+
|
|
|
+ view.beforeRender && view.beforeRender();
|
|
|
|
|
|
if(view.render){
|
|
|
if(!view.render($.extend({}, params, {
|
|
@@ -154093,7 +154316,7 @@ ENDSEC
|
|
|
|
|
|
this.dispatchEvent({type: "render.end", viewer: this, viewport:view });
|
|
|
view.needRender = false;
|
|
|
-
|
|
|
+ view.lastRenderTime = Date.now();
|
|
|
});
|
|
|
|
|
|
|
|
@@ -156929,9 +157152,10 @@ ENDSEC
|
|
|
//add:
|
|
|
async function loadFile(path, params , callback, onError){
|
|
|
params = params || {};
|
|
|
- if(Potree.fileServer){
|
|
|
-
|
|
|
- Potree.fileServer.get(path, { params }).then(data=>{
|
|
|
+ let fetchMethod = params.fetchMethod || 'get';
|
|
|
+ delete params.fetchMethod;
|
|
|
+ if(Potree.fileServer){
|
|
|
+ Potree.fileServer[fetchMethod](path, { params }).then(data=>{
|
|
|
if(data.data)data = data.data;
|
|
|
if(data.data)data = data.data; //融合页面getdataset需要查找两次data
|
|
|
callback && callback(data);
|
|
@@ -156947,15 +157171,17 @@ ENDSEC
|
|
|
index ++;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+ let info={};
|
|
|
+ if(fetchMethod == 'post')info.method = 'POST';
|
|
|
|
|
|
- let response = await fetch(path);
|
|
|
+ let response = await fetch(path, info);
|
|
|
let text = await response.text();
|
|
|
var data = JSON.parse(text);
|
|
|
if(data.data) data = data.data;
|
|
|
callback && callback(data);
|
|
|
return data
|
|
|
}catch(e){
|
|
|
+ console.log('loadFile出错', e);
|
|
|
onError && onError(e);
|
|
|
}
|
|
|
|
|
@@ -157072,10 +157298,10 @@ ENDSEC
|
|
|
/* if(Potree.fileServer){
|
|
|
path = `/laser/filter/${Potree.settings.number}/query`
|
|
|
}else{ */
|
|
|
- path = `${Potree.settings.urls.prefix}/init/getSceneNumVersion/${Potree.settings.number}`;
|
|
|
-
|
|
|
+ path = `/laser/init/getSceneNumVersion/${Potree.settings.number}`;
|
|
|
+ //api/laser/init
|
|
|
//}
|
|
|
- return loadFile(path, {}, callback)
|
|
|
+ return loadFile(path, {fetchMethod:'post'}, callback, callback)
|
|
|
|
|
|
}
|
|
|
|