|
@@ -4318,8 +4318,8 @@
|
|
|
}
|
|
|
},
|
|
|
adjustSpeed: function adjustSpeed(e, t) {
|
|
|
- for (var u = this.getById(e), duration = 0; duration < u.length; duration++) {
|
|
|
- var r = u[duration];
|
|
|
+ for (var u = this.getById(e), n = 0; n < u.length; n++) {
|
|
|
+ var r = u[n];
|
|
|
r.duration /= t, r.current /= t;
|
|
|
}
|
|
|
},
|
|
@@ -4593,8 +4593,12 @@
|
|
|
},
|
|
|
replaceAll: function replaceAll(str, f, e) {
|
|
|
//f全部替换成e
|
|
|
+
|
|
|
+ /* if(str.replaceAll ) return str.replaceAll(f, e)
|
|
|
+ else{ */
|
|
|
var reg = new RegExp(f, "g"); //创建正则RegExp对象
|
|
|
- return str.replace(reg, e);
|
|
|
+ return str.replace(reg, e); //str.split(f).join(e);
|
|
|
+ //}
|
|
|
},
|
|
|
dealURL(url) {
|
|
|
var urlNew = this.replaceAll(url, "\\+", "%2B"); // 浏览器似乎不支持访问带+的地址
|
|
@@ -4875,6 +4879,46 @@
|
|
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
return dataUrl;
|
|
|
},
|
|
|
+ /* 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) {
|
|
|
var otherReplaces = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
|
|
|
//部分shader要根据webgl版本作更改
|
|
@@ -4889,24 +4933,24 @@
|
|
|
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 ');
|
|
|
+ newShader = this.replaceAll(newShader, 'varying ', shaderType == 'vs' ? 'out ' : 'in ');
|
|
|
+ newShader = this.replaceAll(newShader, 'attribute ', 'in ');
|
|
|
if (shaderType == 'fs') {
|
|
|
- newShader = newShader.replaceAll('gl_FragColor', 'fragColor');
|
|
|
+ newShader = this.replaceAll(newShader, '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 = 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 = newShader.replaceAll('defined(GL_EXT_frag_depth) &&', '');
|
|
|
+ newShader = this.replaceAll(newShader, 'defined(GL_EXT_frag_depth) &&', '');
|
|
|
otherReplaces.forEach(_ref2 => {
|
|
|
var {
|
|
|
oldStr,
|
|
|
newStr
|
|
|
} = _ref2;
|
|
|
- newShader = newShader.replaceAll(oldStr, newStr);
|
|
|
+ newShader = this.replaceAll(newShader, oldStr, newStr);
|
|
|
});
|
|
|
return newShader;
|
|
|
};
|
|
@@ -19637,8 +19681,8 @@
|
|
|
};
|
|
|
Utils.datasetRotTransform = function () {
|
|
|
var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
|
- var pointcloud = o.pointcloud || viewer.scene.pointclouds.find(e => e.dataset_id == o.datasetId);
|
|
|
- if (pointcloud) {
|
|
|
+ var object = o.pointcloud || viewer.scene.pointclouds.find(e => e.dataset_id == o.datasetId) || o.object || viewer.objs.children.find(e => e.dataset_id == o.datasetId);
|
|
|
+ if (object) {
|
|
|
var matrix, newMatrix, result;
|
|
|
if (o.rotation) {
|
|
|
matrix = new Matrix4().makeRotationFromEuler(o.rotation);
|
|
@@ -19649,7 +19693,13 @@
|
|
|
} else {
|
|
|
return;
|
|
|
}
|
|
|
- var rotateMatrix = o.fromDataset ? pointcloud.rotateMatrix : pointcloud.rotateInvMatrix;
|
|
|
+ var rotateMatrix = o.fromDataset ? object.rotateMatrix : object.rotateInvMatrix;
|
|
|
+ if (!rotateMatrix) {
|
|
|
+ rotateMatrix = new Matrix4().makeRotationFromEuler(object.rotation); //如果是没有漫游点的模型,在此临时获取一个,但和有漫游点的比会有所不同,因为没有初始旋转(如转90度)
|
|
|
+ if (o.toDataset) {
|
|
|
+ rotateMatrix.invert();
|
|
|
+ }
|
|
|
+ }
|
|
|
newMatrix = new Matrix4().multiplyMatrices(rotateMatrix, matrix);
|
|
|
if (o.getRotation) {
|
|
|
result = new Euler().setFromRotationMatrix(newMatrix);
|
|
@@ -22614,7 +22664,7 @@
|
|
|
isOfficial: false,
|
|
|
webSite: 'testdata',
|
|
|
//正式:'datav1', //不同环境对应的静态文件的地址不同
|
|
|
-
|
|
|
+ // language : "zh"
|
|
|
isLocal: false,
|
|
|
//是否本地 局域网版本
|
|
|
libsUrl: '../libs/',
|
|
@@ -23388,14 +23438,16 @@
|
|
|
//if(Potree.settings.mapCompany == 'google')return
|
|
|
if (style == this.style) return;
|
|
|
if (Potree.settings.mapCompany == 'google') {
|
|
|
- if (style == 'satellite') {
|
|
|
- //卫星
|
|
|
- this.baseUrl = "https://mt2.google.com/vt/lyrs=y@159000000&hl=zh-CN&gl=cn&x=${x}&y=${y}&z=${z}&s=mt1"; /* "http://mt2.google.cn/vt/lyrs=m@177000000&hl=zh-CN&gl=cn&src=app&x=${x}&y=${y}&z=${z}" */ //最高只到19
|
|
|
- this.maxDepth = 22;
|
|
|
- } else {
|
|
|
- this.baseUrl = "https://mt2.google.com/vt/lyrs=m@159000000&hl=zh-CN&gl=cn&x=${x}&y=${y}&z=${z}&s=mt1"; /* "http://mt2.google.cn/vt/lyrs=m@177000000&hl=zh-CN&gl=cn&src=app&x=${x}&y=${y}&z=${z}" */ //最高只到19
|
|
|
- this.maxDepth = 22;
|
|
|
- }
|
|
|
+ var [lang, glPos] = {
|
|
|
+ 'zh': ["zh-CN", "cn"],
|
|
|
+ 'en': ["en-US"],
|
|
|
+ //范围大所以不指定地理位置 。
|
|
|
+ 'ja': ["ja-JP", "JP"],
|
|
|
+ 'kr': ["ko-KR", "KR"]
|
|
|
+ }[Potree.settings.language] || [];
|
|
|
+ this.baseUrl = "https://mt2.google.com/vt/lyrs=" + (style == 'satellite' ? "y" : "m") + "@159000000" + (lang ? "&hl=" + lang : '') + (glPos ? "&gl=" + glPos : '') + "&x=${x}&y=${y}&z=${z}&s=mt1";
|
|
|
+ this.maxDepth = 22;
|
|
|
+
|
|
|
/* 1)lyrs= 表示的是图层类型,即瓦片类型,具体含义如下:
|
|
|
m:路线图
|
|
|
t:地形图
|
|
@@ -23403,9 +23455,12 @@
|
|
|
s:卫星图
|
|
|
y:带标签的卫星图
|
|
|
h:标签层(路名、地名等)
|
|
|
- 2)& gl=CN
|
|
|
+ 2)& gl=CN 指定地理区域
|
|
|
谷歌地图针对中国有两套坐标,一套做了偏移,一套没有。经测试在url加入gl=cn地图会有偏移。
|
|
|
- Tips:如果谷歌地图和RTK测量的WGS84坐标有偏差,可以尝试在url里去掉& gl=cn。
|
|
|
+ Tips:如果谷歌地图和RTK测量的WGS84坐标有偏差,可以尝试在url里去掉& gl=cn。(摘自网上)
|
|
|
+
|
|
|
+ 通义千问:如果不指定gl参数,Google将使用默认值或基于其他因素(如IP地址)来推断用户的地理区域。这通常不会导致地图数据的不准确性,但可能会影响本地化信息的显示。地图上的标签(如街道名称、城市名称等)可能不会以最合适的语言显示。地址格式和拼写可能不符合当地标准
|
|
|
+
|
|
|
5)&hl=
|
|
|
设置地图注记文字语言类型,缺省默认为中文。
|
|
|
hl=nl 中英双语
|
|
@@ -27752,7 +27807,7 @@
|
|
|
//2048
|
|
|
this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, c, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV_NARROW);
|
|
|
}
|
|
|
- if (this.canDownloadSize(h)) {
|
|
|
+ if (this.canDownloadSize(h) && this.priorityCriteria.pano.pointcloud.tileRes != '2k') {
|
|
|
//4096
|
|
|
this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, h, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV_NARROW);
|
|
|
}
|
|
@@ -27767,7 +27822,7 @@
|
|
|
//2048
|
|
|
this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, c, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV);
|
|
|
}
|
|
|
- if (this.canDownloadSize(h)) {
|
|
|
+ if (this.canDownloadSize(h) && this.priorityCriteria.pano.pointcloud.tileRes != '2k') {
|
|
|
//4096
|
|
|
this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, h, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV);
|
|
|
}
|
|
@@ -28831,6 +28886,7 @@
|
|
|
tileIndex = o.tileIndex,
|
|
|
sceneCode = o.pano.pointcloud.sceneCode,
|
|
|
useV4url = Potree.settings.useV4url && o.pano.pointcloud.datasetData.sceneVersion == 'V4'; //v4的全景图等路径不一样
|
|
|
+ var resolution = o.pano.pointcloud.tileRes || '4k';
|
|
|
var metadata = {
|
|
|
sceneScheme: 10
|
|
|
};
|
|
@@ -28851,7 +28907,7 @@
|
|
|
} else {
|
|
|
//阿里云oss的规则 if (metadata.sceneScheme == 10)
|
|
|
|
|
|
- d = 'tiles/4k/' + id + '_skybox' + h + '.jpg?x-oss-process=';
|
|
|
+ d = 'tiles/' + resolution + '/' + id + '_skybox' + h + '.jpg?x-oss-process=';
|
|
|
if (e[panoSize] == '512') {
|
|
|
d += 'image/resize,h_512';
|
|
|
} else {
|
|
@@ -28860,7 +28916,7 @@
|
|
|
//https://4dkk.4dage.com/images/imagesx4iqYDG3/tiles/4k/122_skybox0.jpg?x-oss-process=image/resize,m_lfit,w_1024/crop,w_512,h_512,x_511,y_0
|
|
|
d += 'image/resize,m_lfit,w_' + panoSize + '/crop,w_512,h_512,';
|
|
|
} else {
|
|
|
- d = 'tiles/4k/' + id + '_skybox' + h + '.jpg?x-oss-process=image/crop,w_512,h_512,';
|
|
|
+ d = 'tiles/' + resolution + '/' + id + '_skybox' + h + '.jpg?x-oss-process=image/crop,w_512,h_512,';
|
|
|
}
|
|
|
//起始位置
|
|
|
if (t.tileX == 0) {
|
|
@@ -29263,7 +29319,7 @@
|
|
|
}
|
|
|
queueTileUpload(e, t, i) {
|
|
|
var n = this.getActiveRenderTargetDescriptor(e.panoId);
|
|
|
- if (this.isRenderTargetDescriptorValid(n) && e.downloaded && !this.isTileUploaded(e) && (!e.uploadQueued || i) && (!(e.panoSize > this.qualityManager.getMaxNavPanoSize()) || this.zoomingActive)) {
|
|
|
+ if (this.isRenderTargetDescriptorValid(n) && e.downloaded && !this.isTileUploaded(e) && (!e.uploadQueued || i) && (!(e.panoSize > this.qualityManager.getMaxNavPanoSize()) || this.zoomingActive && viewer.images360.getPano(e.panoId).tileRes != '2k')) {
|
|
|
var r = this.getUploadQueueForPano(e.panoId);
|
|
|
//console.log(window.sceneName, 'queueTileUpload: ', e.panoId, e.tileIndex, i)
|
|
|
if (i) {
|
|
@@ -30320,20 +30376,7 @@
|
|
|
this.cube.material.defines.depth_background = ''; //skybox的深度改得向后一些, 避免盖住chunk,造成坑坑洼洼
|
|
|
|
|
|
this.addEventListener('endChangeMode', e => {
|
|
|
- var _this$currentPano;
|
|
|
- if ((_this$currentPano = this.currentPano) !== null && _this$currentPano !== void 0 && (_this$currentPano = _this$currentPano.pointcloud) !== null && _this$currentPano !== void 0 && _this$currentPano.is4dkkModel) {
|
|
|
- var model = this.currentPano.pointcloud;
|
|
|
- if (model.fileType == '3dTiles') {
|
|
|
- viewer.setAllTilesets(model, child => {
|
|
|
- child.runtime.limit2lowestDepth(e.mode == 'showPanos');
|
|
|
- child.runtime.getTileset().tiles.forEach(e => {
|
|
|
- this.judgeModelMat(e.tileContent);
|
|
|
- });
|
|
|
- });
|
|
|
- } else {
|
|
|
- this.judgeModelMat(model);
|
|
|
- }
|
|
|
- }
|
|
|
+ viewer.objs.children.forEach(e => this.changeModelMat(e)); //干脆全部换,就不容易错
|
|
|
});
|
|
|
}
|
|
|
}
|
|
@@ -30754,13 +30797,28 @@
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
- judgeModelMat(object) {
|
|
|
+ changeModelMat(model /* , isCurModel */) {
|
|
|
+ if (model !== null && model !== void 0 && model.is4dkkModel) {
|
|
|
+ if (model.fileType == '3dTiles') {
|
|
|
+ viewer.setAllTilesets(model, child => {
|
|
|
+ child.runtime.limit2lowestDepth(Potree.settings.displayMode == 'showPanos');
|
|
|
+ child.runtime.getTileset().tiles.forEach(e => {
|
|
|
+ this.judgeModelMat(e.tileContent /* , isCurModel */);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this.judgeModelMat(model /* , isCurModel */);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ judgeModelMat(object /* , isCurModel */) {
|
|
|
if (!(Potree.settings.mergeType2 && Potree.settings.modelSkybox)) return;
|
|
|
object.traverse(mesh => {
|
|
|
if (mesh.material) {
|
|
|
if (!mesh.materialOutside) {
|
|
|
mesh.materialOutside = mesh.material;
|
|
|
}
|
|
|
+ //mesh.material = Potree.settings.displayMode == 'showPanos' && (this.nextPano?.pointcloud == object || this.currentPano.pointcloud == object || isCurModel) ? this.materialInside : mesh.materialOutside
|
|
|
mesh.material = Potree.settings.displayMode == 'showPanos' ? this.materialInside : mesh.materialOutside;
|
|
|
Potree.Utils.setObjectLayers(mesh, Potree.settings.displayMode == 'showPanos' ? 'skybox' : 'model'); //为了渲染到rtEDL
|
|
|
}
|
|
@@ -31436,23 +31494,25 @@
|
|
|
|
|
|
var getNeighbour = (mainPano, subPano) => {
|
|
|
var dirPoints = [[subPano.position, mainPano.position]]; //注: 点A能到B不代表点B能到A,因为拍摄时物体会移动,或点位相对位置不对,无论是否是意外遮挡都且记下来,反正最后只要有一方可行就算相邻。
|
|
|
+ if (new Vector2().subVectors(subPano.position, mainPano.position).length() > 1e-4) {
|
|
|
+ //xy都不同
|
|
|
|
|
|
- if (dis < 20) {
|
|
|
- //在远处去掉对floorPosition的判断
|
|
|
- dirPoints.push([subPano.floorPosition.clone().add(new Vector3(0, 0, 0.1)), mainPano.position]);
|
|
|
- }
|
|
|
- if (dis < 12) {
|
|
|
- //为了防止楼梯拐角、杂点遮挡。 尽量只在穿墙时不可通行
|
|
|
- dirPoints.push([subPano.position.clone().add(new Vector3(0, 0, 0.8)), mainPano.position]);
|
|
|
- var normal = math.getNormal2d({
|
|
|
- p1: subPano.position,
|
|
|
- p2: mainPano.position
|
|
|
- }).multiplyScalar(0.3); //左右方向
|
|
|
+ if (dis < 20) {
|
|
|
+ //在远处去掉对floorPosition的判断
|
|
|
+ dirPoints.push([subPano.floorPosition.clone().add(new Vector3(0, 0, 0.1)), mainPano.position]);
|
|
|
+ }
|
|
|
+ if (dis < 12) {
|
|
|
+ //为了防止楼梯拐角、杂点遮挡。 尽量只在穿墙时不可通行
|
|
|
+ dirPoints.push([subPano.position.clone().add(new Vector3(0, 0, 0.8)), mainPano.position]);
|
|
|
+ var normal = math.getNormal2d({
|
|
|
+ p1: subPano.position,
|
|
|
+ p2: mainPano.position
|
|
|
+ }).multiplyScalar(0.3); //左右方向
|
|
|
|
|
|
- dirPoints.push([subPano.position.clone().add(new Vector3(normal.x, normal.y, 0.1)), mainPano.position]);
|
|
|
- dirPoints.push([subPano.position.clone().add(new Vector3(-normal.x, -normal.y, 0.1)), mainPano.position]);
|
|
|
+ dirPoints.push([subPano.position.clone().add(new Vector3(normal.x, normal.y, 0.1)), mainPano.position]);
|
|
|
+ dirPoints.push([subPano.position.clone().add(new Vector3(-normal.x, -normal.y, 0.1)), mainPano.position]);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
//console.warn('getNeighbour', mainPano.id,subPano.id)
|
|
|
for (var i = 0; i < dirPoints.length; i++) {
|
|
|
var dir = new Vector3().subVectors(dirPoints[i][0], dirPoints[i][1]).normalize();
|
|
@@ -32091,6 +32151,10 @@
|
|
|
this.panoRenderer.renderPanoTiles(pano.id, null, !1, !1);
|
|
|
pano.setZoomed(ifZoom);
|
|
|
};
|
|
|
+ if (currentPano.pointcloud.tileRes == '2k') {
|
|
|
+ //融合页面
|
|
|
+ return currentPano.zoomed && o(currentPano, !1);
|
|
|
+ }
|
|
|
if (r && (!currentPano.zoomed || this.qualityManager.zoomLevelResolution && this.qualityManager.zoomLevelResolution != '4k')) {
|
|
|
//needZoom
|
|
|
currentPano.zoomed || o(currentPano, !0);
|
|
@@ -34996,7 +35060,8 @@
|
|
|
var easeName = arguments.length > 4 ? arguments[4] : undefined;
|
|
|
var callback = arguments.length > 5 ? arguments[5] : undefined;
|
|
|
//前两个参数有xy即可
|
|
|
- endPosition = new Vector3(endPosition.x, endPosition.y, Potree.config.map.cameraHeight);
|
|
|
+ var z = Math.max(Potree.config.map.cameraHeight, endPosition.z + (boundSize !== null && boundSize !== void 0 && boundSize.z ? boundSize.z / 2 : 0));
|
|
|
+ endPosition = new Vector3(endPosition.x, endPosition.y, z);
|
|
|
this.view.moveOrthoCamera(this.viewports[0], {
|
|
|
endPosition,
|
|
|
boundSize,
|
|
@@ -36139,6 +36204,7 @@
|
|
|
//2022-12-21又换回非固定值。因为有的场景如SS-t-t01myDqnfE的两个数据集密集程度差别很大,应该将稀疏点云的大小设置的大些。 但是这样的缺点是两个数据集因相接处有大有小无法融合。
|
|
|
size = _base * 20 * num_;
|
|
|
}
|
|
|
+ //不同数据集点云最高级别时的间距不同,但不知道如何计算, 级别越高点云越密,spacing越大初始级别越密。 但实际并非2的level次方,底数可能1-2之间
|
|
|
}
|
|
|
//console.log('changePointSize:' + this.dataset_id + ' , num: ' + (num && num.toPrecision(3)) + ' , size: ' + size.toPrecision(3), 'nodeMaxLevel', nodeMaxLevel.toPrecision(3), 'testMaxNodeCount',this.testMaxNodeCount /* this.material.spacing */)
|
|
|
if (size) {
|
|
@@ -75193,7 +75259,7 @@
|
|
|
domElement = document;
|
|
|
}
|
|
|
Object3D.call(this);
|
|
|
- this.visible = false;
|
|
|
+ Potree.Utils.updateVisible(this, 'attach', false);
|
|
|
this.domElement = domElement;
|
|
|
var _gizmo = new TransformControlsGizmo(options);
|
|
|
this.add(_gizmo);
|
|
@@ -75337,11 +75403,12 @@
|
|
|
};
|
|
|
|
|
|
// Set current object
|
|
|
- this.attach = function (object) {
|
|
|
+ this.attach = function (object, clickPos) {
|
|
|
this.object = object;
|
|
|
- this.visible = true;
|
|
|
+ Potree.Utils.updateVisible(this, 'attach', true);
|
|
|
//Config.keyCon = false;//add
|
|
|
//this.linesAssistance.setVisible(true)
|
|
|
+ this.clickPos = clickPos !== null && clickPos !== void 0 && clickPos.isVector3 ? clickPos : null;
|
|
|
viewer.dispatchEvent('content_changed');
|
|
|
return this;
|
|
|
};
|
|
@@ -75349,10 +75416,9 @@
|
|
|
// Detatch from object
|
|
|
this.detach = function () {
|
|
|
this.object = undefined;
|
|
|
- this.visible = false;
|
|
|
this.axis = null;
|
|
|
//Config.keyCon = true;//add
|
|
|
-
|
|
|
+ Potree.Utils.updateVisible(this, 'attach', false);
|
|
|
//this.linesAssistance.setVisible(false)
|
|
|
viewer.dispatchEvent('content_changed');
|
|
|
return this;
|
|
@@ -75403,9 +75469,11 @@
|
|
|
this.object.updateMatrixWorld();
|
|
|
this.object.parent.matrixWorld.decompose(parentPosition, parentQuaternion, parentScale);
|
|
|
this.object.matrixWorld.decompose(worldPosition, worldQuaternion, worldScale);
|
|
|
-
|
|
|
- //add
|
|
|
- if (this.object.boundingBox) {
|
|
|
+ if (Potree.settings.mergeTransCtlOnClick && this.mode == 'translate' && this.clickPos) {
|
|
|
+ //允许位移控件出现在点击的位置
|
|
|
+ var pos = this.clickPos.clone().applyMatrix4(this.object.matrixWorld);
|
|
|
+ worldPosition.copy(pos);
|
|
|
+ } else if (this.object.boundingBox) {
|
|
|
var boundingBox = this.object.boundingBox.clone().applyMatrix4(this.object.matrixWorld);
|
|
|
boundingBox.getCenter(worldPosition); //bound中心
|
|
|
if (this.pivotOnBottom) {
|
|
@@ -76732,11 +76800,20 @@
|
|
|
if (e.intersect) {
|
|
|
var object = e.intersect.object || e.intersect.pointcloud;
|
|
|
var objects = this.getAllObjects();
|
|
|
+ var posInModel = Potree.Utils.datasetPosTransform({
|
|
|
+ toDataset: true,
|
|
|
+ position: e.intersect.location.clone(),
|
|
|
+ object
|
|
|
+ });
|
|
|
if (objects.includes(object) && this.selected != object) {
|
|
|
- this.selectModel(object);
|
|
|
+ this.selectModel(object, posInModel);
|
|
|
} else {
|
|
|
//if(!viewer.inputHandler.selection[0]){//正在平移和旋转,不允许取消
|
|
|
- this.selectModel(null);
|
|
|
+ if (this.selected == object && this.transformControls.mode == 'translate') {
|
|
|
+ this.selectModel(object, posInModel); //update click pos
|
|
|
+ } else {
|
|
|
+ this.selectModel(null);
|
|
|
+ }
|
|
|
//}
|
|
|
}
|
|
|
} else {
|
|
@@ -76985,6 +77062,13 @@
|
|
|
model = this.selected;
|
|
|
state = false;
|
|
|
}
|
|
|
+ if (!by2d && model) {
|
|
|
+ model.dispatchEvent({
|
|
|
+ type: 'changeSelect',
|
|
|
+ selected: state,
|
|
|
+ clickPos: state
|
|
|
+ });
|
|
|
+ }
|
|
|
if (state) {
|
|
|
if (this.selected) {
|
|
|
if (this.selected == model) return;else {
|
|
@@ -77008,12 +77092,6 @@
|
|
|
this.transformControls.detach(); //viewer.transformObject(null);
|
|
|
//console.log('selectModel', null)
|
|
|
}
|
|
|
- if (!by2d && model) {
|
|
|
- model.dispatchEvent({
|
|
|
- type: 'changeSelect',
|
|
|
- selected: state
|
|
|
- });
|
|
|
- }
|
|
|
},
|
|
|
updateBoxHelper(model) {
|
|
|
var size = new Vector3();
|
|
@@ -77028,7 +77106,7 @@
|
|
|
this.boxHelper.quaternion.copy(model.quaternion);
|
|
|
},
|
|
|
showModelOutline(model, state) {
|
|
|
- if (Potree.settings.mergeType2 || model ? model.fileType == '3dgs' : this.boxHelper.visible) {
|
|
|
+ if (Potree.settings.mergeType2 || (model ? model.fileType == '3dgs' : this.boxHelper.visible)) {
|
|
|
//高斯很卡
|
|
|
if (state !== false) {
|
|
|
this.updateBoxHelper(model);
|
|
@@ -77186,7 +77264,6 @@
|
|
|
//反向求transformMatrix 参考Alignment.js 移动漫游点
|
|
|
if (model.isPointcloud && model.transformMatrix) {
|
|
|
model.transformMatrix.multiplyMatrices(model.matrix, model.pos1MatrixInvert);
|
|
|
- model.transformInvMatrix.copy(model.transformMatrix).invert();
|
|
|
model.rotateMatrix = new Matrix4().makeRotationFromEuler(model.rotation);
|
|
|
model.panos.forEach(e => e.transformByPointcloud());
|
|
|
} else if (model.panos) {
|
|
@@ -77195,6 +77272,10 @@
|
|
|
model.panos.forEach(e => e.transformByPointcloud());
|
|
|
model.bound = model.boundingBox.clone().applyMatrix4(model.matrixWorld);
|
|
|
}
|
|
|
+ if (model.panos) {
|
|
|
+ model.transformInvMatrix.copy(model.transformMatrix).invert();
|
|
|
+ model.rotateInvMatrix.copy(model.rotateMatrix).invert();
|
|
|
+ }
|
|
|
model.lastMatrixWorld = model.matrixWorld.clone();
|
|
|
viewer.dispatchEvent('content_changed');
|
|
|
viewer.mapViewer && Potree.settings.showObjectsOnMap && viewer.mapViewer.dispatchEvent('content_changed');
|
|
@@ -77345,8 +77426,10 @@
|
|
|
|
|
|
要注意getHoveredElements只在getIntersect时才使interactables包含加载的model, 也就是model上不能有使之成为interactables的事件,否则在鼠标hover到模型上开始转动的一瞬间很卡。
|
|
|
|
|
|
-
|
|
|
-
|
|
|
+ 控制台断开完全重合的漫游点的方法
|
|
|
+ window.pano1 = viewer.modules.PanoEditor.selectedPano //选中第一个点后输入这行,得到第一个漫游点
|
|
|
+ window.pano2 = viewer.modules.PanoEditor.selectedPano //选中第二个点后输入这行,得到第二个漫游点
|
|
|
+ viewer.modules.PanoEditor.linkChange(window.pano1, window.pano2, 'remove') //断开链接
|
|
|
|
|
|
|
|
|
*/
|
|
@@ -79792,6 +79875,182 @@
|
|
|
removeAnimation(animation) {
|
|
|
animation.dispatchEvent('dispose');
|
|
|
viewer.scene.removeCameraAnimation(animation);
|
|
|
+ },
|
|
|
+ createMulAnimation(data) {
|
|
|
+ //新版,包含漫游点
|
|
|
+ var event_ = new EventDispatcher();
|
|
|
+ var sections = []; //分段, 分成animation和漫游点
|
|
|
+ var aniIndex = 0;
|
|
|
+ var curAni,
|
|
|
+ addAnimation = () => {
|
|
|
+ if (curAni) {
|
|
|
+ var data_ = {
|
|
|
+ name: 'animation_' + aniIndex,
|
|
|
+ duration: curAni.slice(0, curAni.length - 1).reduce(function (total, currentValue) {
|
|
|
+ return total + currentValue.time;
|
|
|
+ }, 0),
|
|
|
+ //总时长(要去掉最后一个,因为已到终点,该点time无意义)
|
|
|
+ useDurSlice: data.useDurSlice,
|
|
|
+ points: curAni
|
|
|
+ };
|
|
|
+ var ani = this.createAnimation(data_);
|
|
|
+ sections.push(ani);
|
|
|
+ ani.originIndexStart = data.points.indexOf(curAni[0]);
|
|
|
+ ani.addEventListener('updateCurrentIndex', e => {
|
|
|
+ emitIndex(e.currentIndex);
|
|
|
+ });
|
|
|
+ curAni = null;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ data.points.forEach((e, i) => {
|
|
|
+ //切分为若干个animation,中间是漫游点的衔接
|
|
|
+ if (e.panoId != void 0) {
|
|
|
+ //暂定:有panoId的都是全景图模式
|
|
|
+ var pano = e.model.panos.find(a => a.originID == e.panoId);
|
|
|
+ if (pano) {
|
|
|
+ addAnimation(); //如果前面是动画,先截断
|
|
|
+ e.pano = pano;
|
|
|
+ e.rotInModel = new Quaternion().fromArray(e.rotInModel);
|
|
|
+ e.quaternion = Potree.Utils.datasetRotTransform({
|
|
|
+ fromDataset: true,
|
|
|
+ quaternion: e.rotInModel,
|
|
|
+ getQuaternion: true,
|
|
|
+ object: e.model
|
|
|
+ });
|
|
|
+ sections.push(e);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (curAni) {
|
|
|
+ curAni.push(e);
|
|
|
+ } else {
|
|
|
+ //非pano
|
|
|
+ if (sections.length > 0) {
|
|
|
+ var last = sections[sections.length - 1]; //因为要从上一个pano出来,所以起始点是上一个pano
|
|
|
+ last.position = last.pano.position;
|
|
|
+ last.target = last.position.clone().add(new Vector3(0, 0, -1).applyQuaternion(last.quaternion));
|
|
|
+ curAni = [last, e];
|
|
|
+ } else {
|
|
|
+ curAni = [e];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ addAnimation();
|
|
|
+ var currentPlay;
|
|
|
+ var emitIndex = function emitIndex() {
|
|
|
+ var indexInAni = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
|
+ var ani = sections[currentPlay];
|
|
|
+ var currentIndex = 0;
|
|
|
+ if (ani instanceof CameraAnimation$1) {
|
|
|
+ currentIndex = ani.originIndexStart + indexInAni;
|
|
|
+ } else {
|
|
|
+ currentIndex = Math.max(0, data.points.indexOf(ani) - 1);
|
|
|
+ }
|
|
|
+ event_.dispatchEvent({
|
|
|
+ type: 'updateCurrentIndex',
|
|
|
+ currentIndex
|
|
|
+ });
|
|
|
+ };
|
|
|
+ var result = {
|
|
|
+ event_,
|
|
|
+ play() {
|
|
|
+ //从头播放
|
|
|
+
|
|
|
+ var playNext = index => {
|
|
|
+ if (index == sections.length) {
|
|
|
+ return event_.dispatchEvent('playDone');
|
|
|
+ }
|
|
|
+ var ani = sections[index];
|
|
|
+ currentPlay = index;
|
|
|
+ emitIndex();
|
|
|
+ if (ani instanceof CameraAnimation$1) {
|
|
|
+ Potree.settings.displayMode = 'showPointCloud';
|
|
|
+ ani.addEventListener('playDone', () => {
|
|
|
+ playNext(index + 1);
|
|
|
+ }, {
|
|
|
+ once: true
|
|
|
+ });
|
|
|
+ ani.play();
|
|
|
+ } else {
|
|
|
+ var pano = ani.pano;
|
|
|
+ var last = sections[index - 1],
|
|
|
+ duration,
|
|
|
+ quaternion = ani.quaternion;
|
|
|
+ if (last) {
|
|
|
+ if (last instanceof CameraAnimation$1) {
|
|
|
+ duration = last.durations[last.durations.length - 1]; //最后一个时间
|
|
|
+ } else {
|
|
|
+ duration = last.time;
|
|
|
+ }
|
|
|
+ duration *= 1000;
|
|
|
+ } else {
|
|
|
+ duration = 600; //起始
|
|
|
+ }
|
|
|
+ viewer.images360.flyToPano({
|
|
|
+ pano,
|
|
|
+ quaternion,
|
|
|
+ duration,
|
|
|
+ callback: () => {
|
|
|
+ var next = () => {
|
|
|
+ var stayTime = (!sections[index - 1] || sections[index - 1] instanceof CameraAnimation$1) && sections[index + 1] && sections[index + 1] instanceof CameraAnimation$1 ? 1000 : 300; //前后都是点云模式的话停留久一点。最好在页面上能设置
|
|
|
+ console.log('stayTime', stayTime);
|
|
|
+ setTimeout(() => {
|
|
|
+ currentPlay != void 0 && playNext(index + 1);
|
|
|
+ }, stayTime); //稍作停留,不然点云-全景-点云的话根本看不到全景
|
|
|
+ };
|
|
|
+ if ( /* ani.displayMode == 'showPanos' && */Potree.settings.displayMode != 'showPanos') {
|
|
|
+ //刚加载完就飞走吗?
|
|
|
+ Potree.settings.displayMode = 'showPanos';
|
|
|
+ viewer.images360.addEventListener('endChangeMode', () => {
|
|
|
+ next();
|
|
|
+ }, {
|
|
|
+ once: true
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ next();
|
|
|
+ }
|
|
|
+ //
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+ playNext(0);
|
|
|
+ },
|
|
|
+ stop() {
|
|
|
+ var ani = sections[currentPlay];
|
|
|
+ if (ani instanceof CameraAnimation$1) {
|
|
|
+ ani.pause();
|
|
|
+ } else {
|
|
|
+ var view = viewer.mainViewport.view;
|
|
|
+ if (!view.isFlying('pos')) {
|
|
|
+ //前后是相同漫游点,仅旋转
|
|
|
+ view.cancelFlying('rotate');
|
|
|
+ } else {
|
|
|
+ //加快结束
|
|
|
+ var o = transitions.getById(view.FlyTransition)[0];
|
|
|
+ var restDur = o.duration - o.current;
|
|
|
+ var hopeStopTime = 300; //希望最多等待时间
|
|
|
+ if (restDur > hopeStopTime) {
|
|
|
+ var r = o.duration / (o.current + hopeStopTime);
|
|
|
+ transitions.adjustSpeed(view.FlyTransition, r);
|
|
|
+ transitions.adjustSpeed(view.LookTransition, r);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //如果有地图,还要改地图的view
|
|
|
+ }
|
|
|
+ currentPlay = null;
|
|
|
+ },
|
|
|
+ remove() {
|
|
|
+ sections.forEach(ani => {
|
|
|
+ if (ani instanceof CameraAnimation$1) {
|
|
|
+ CamAniEditor.removeAnimation(ani);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ //再把中间的缓动去除
|
|
|
+ };
|
|
|
+ return result;
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -89821,7 +90080,12 @@
|
|
|
}); //更新viewports相机透视 使focusOnObject在此窗口大小下
|
|
|
|
|
|
prisms.forEach(prism => {
|
|
|
- points.push(...prism.points);
|
|
|
+ var prismPoints = prism.points.slice();
|
|
|
+ if (prism.baseModel) {
|
|
|
+ var currentBound = prism.baseModel.currentBound || prism.baseModel.boundingBox.clone().applyMatrix4(prism.baseModel.matrixWorld);
|
|
|
+ prismPoints = prismPoints.map(e => e.clone().setZ(Math.max(e.z, currentBound.max.z)));
|
|
|
+ }
|
|
|
+ points.push(...prismPoints);
|
|
|
prism.setSelected(false);
|
|
|
prism.changeStyleForScreenshot(true, {
|
|
|
hideLabel: info.type != 'prism2d-all',
|
|
@@ -90007,10 +90271,12 @@
|
|
|
}
|
|
|
if (o.focusBoundCenter) {
|
|
|
boundOri.getCenter(target);
|
|
|
+ target.z += 1;
|
|
|
}
|
|
|
var boundSizeOri = boundOri.getSize(new Vector3());
|
|
|
- var boundSizeMap = boundSizeOri.clone().multiplyScalar(o.boundExpandRatio || math.linearClamp(Math.max(boundSizeOri.x, boundSizeOri.y), [0.5, 30], [2.5, 1.2])); //为了能同时看清测量线和地图,当测量线较短时,扩大margin,防止地图过度放大
|
|
|
-
|
|
|
+ var expand = o.boundExpandRatio || math.linearClamp(Math.max(boundSizeOri.x, boundSizeOri.y), [0.5, 30], [2.5, 1.2]); //为了能同时看清测量线和地图,当测量线较短时,扩大margin,防止地图过度放大
|
|
|
+ var boundSizeMap = boundSizeOri.clone();
|
|
|
+ boundSizeMap.x *= expand, boundSizeMap.y *= expand;
|
|
|
boundSizeMap.x = Math.max(minBound.x, boundSizeMap.x);
|
|
|
boundSizeMap.y = Math.max(minBound.y, boundSizeMap.y);
|
|
|
this.mapViewer.moveTo(target.clone(), boundSizeMap, duration, o.margin, null, done);
|
|
@@ -92520,7 +92786,7 @@
|
|
|
}
|
|
|
return loadFile(path, null, callback);
|
|
|
}
|
|
|
- function load4dkkPanos(sceneCode, model, done) {
|
|
|
+ function load4dkkPanos(sceneCode, model, done, tileRes) {
|
|
|
//加载四维看看的漫游点并转换
|
|
|
model.is4dkkModel = true;
|
|
|
model.panos = [];
|
|
@@ -92537,9 +92803,12 @@
|
|
|
model.rot1MatrixInvert = rot1M.clone().invert();
|
|
|
model.transformMatrix = new THREE.Matrix4();
|
|
|
model.rotateMatrix = new THREE.Matrix4();
|
|
|
+ model.transformInvMatrix = new THREE.Matrix4();
|
|
|
+ model.rotateInvMatrix = new THREE.Matrix4();
|
|
|
model.datasetData = {
|
|
|
sceneVersion: 'V4'
|
|
|
};
|
|
|
+ model.tileRes = tileRes;
|
|
|
model.sceneCode = sceneCode;
|
|
|
model.bound = new THREE.Box3();
|
|
|
var path = "https://4dkk.4dage.com/scene_view_data/".concat(sceneCode, "/images/vision.txt");
|