|
@@ -4,7 +4,37 @@ import {PointCloudTree, PointCloudTreeNode} from "./PointCloudTree.js";
|
|
|
import {PointCloudOctreeGeometryNode} from "./PointCloudOctreeGeometry.js";
|
|
|
import {Utils} from "./utils.js";
|
|
|
import {PointCloudMaterial} from "./materials/PointCloudMaterial.js";
|
|
|
+import math from "./utils/math.js";
|
|
|
|
|
|
+import {MeshDraw} from "./utils/DrawUtil.js";
|
|
|
+import searchRings from "./utils/searchRings.js";
|
|
|
+import {TextSprite} from './TextSprite'
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const planeGeo = new THREE.PlaneBufferGeometry(1,1);
|
|
|
+
|
|
|
+
|
|
|
+const planeMats = new Map()
|
|
|
+
|
|
|
+let getPlaneMat = (group, removed)=>{
|
|
|
+ let mat = planeMats.get(group)
|
|
|
+ if(mat)return mat
|
|
|
+
|
|
|
+
|
|
|
+ var planeMat = new THREE.MeshBasicMaterial({
|
|
|
+ //color: level == 'removed' ? "#f00" : new THREE.Color(1 - level*0.2, 1,1),
|
|
|
+ color: (new THREE.Color()).setHSL(Math.random(), 0.5, 0.9) ,
|
|
|
+ //color: (new THREE.Color()).setHSL(removed ? 0 : 0.6, Math.random(), 0.9/* Math.random() */) ,
|
|
|
+
|
|
|
+ transparent:true,
|
|
|
+ side:2,
|
|
|
+ opacity: removed ? 0.3 : 0.9,
|
|
|
+ })
|
|
|
+ planeMats.set(group, planeMat)
|
|
|
+ return planeMat
|
|
|
+}
|
|
|
|
|
|
export class PointCloudOctreeNode extends PointCloudTreeNode {
|
|
|
constructor () {
|
|
@@ -236,7 +266,7 @@ export class PointCloudOctree extends PointCloudTree {
|
|
|
// if(geometryNode.name === "r40206"){
|
|
|
// console.log("creating node for r40206");
|
|
|
// }
|
|
|
- let sceneNode = new THREE.Points(geometryNode.geometry, this.material);
|
|
|
+ let sceneNode = new THREE.Points(geometryNode.geometry, this.material); //好像没什么用
|
|
|
sceneNode.name = geometryNode.name;
|
|
|
sceneNode.position.copy(geometryNode.boundingBox.min);
|
|
|
sceneNode.frustumCulled = false;
|
|
@@ -303,8 +333,597 @@ export class PointCloudOctree extends PointCloudTree {
|
|
|
};
|
|
|
geometryNode.oneTimeDisposeHandlers.push(disposeListener);
|
|
|
|
|
|
+
|
|
|
+ //this.buildTexMesh(geometryNode,sceneNode)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
return node;
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ buildTexMesh(geometryNode,sceneNode){
|
|
|
+
|
|
|
+ // viewer.scene.pointclouds.forEach(a=>a.areaPlanes.forEach(e=>e.material = viewer.images360.cube.material))
|
|
|
+
|
|
|
+ let startTime = Date.now()
|
|
|
+
|
|
|
+
|
|
|
+ if(!this.splitSprites){
|
|
|
+ let splitSprites = new THREE.Object3D
|
|
|
+ splitSprites.name = 'splitSprites_'+this.name
|
|
|
+ splitSprites.matrixAutoUpdate = false //同pointcloud一样不自动更新,直接使用
|
|
|
+ splitSprites.matrix.copy(this.matrix)
|
|
|
+ splitSprites.matrixWorld.copy(this.matrixWorld)
|
|
|
+ this.splitSprites = splitSprites
|
|
|
+ viewer.scene.scene.add(splitSprites)
|
|
|
+
|
|
|
+
|
|
|
+ this.areaPlanes = []
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if(this.texMeshUseLevel == void 0 || geometryNode.level == this.texMeshUseLevel){//只需要某一层level的点
|
|
|
+
|
|
|
+ //let spritesGeo = new THREE.BufferGeometry();
|
|
|
+
|
|
|
+ let scaleRatio = 1.4 //稍微放大些,填满缝隙
|
|
|
+ let spriteWidth1 = this.material.spacing / Math.pow(2, geometryNode.level)
|
|
|
+ if(spriteWidth1 > 3)return
|
|
|
+ let spriteWidth = spriteWidth1 * scaleRatio
|
|
|
+
|
|
|
+ if(this.texMeshUseLevel == void 0 ){
|
|
|
+ this.texMeshUseLevel = geometryNode.level
|
|
|
+ console.log('texMeshUseLevel ',geometryNode.level)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ let splitSprites = new THREE.Object3D
|
|
|
+ splitSprites.name = 'sub_splitSprites_'+geometryNode.name
|
|
|
+ splitSprites.position.copy(sceneNode.position)
|
|
|
+ splitSprites.rotation.copy(sceneNode.rotation)
|
|
|
+ this.splitSprites.add(splitSprites)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ let geometry = geometryNode.geometry
|
|
|
+ let count = geometry.attributes.position.count
|
|
|
+
|
|
|
+
|
|
|
+ let end = Math.min(count, 850)
|
|
|
+ let start = Math.min(0, end)
|
|
|
+
|
|
|
+
|
|
|
+ console.warn('check points count:', end-start)
|
|
|
+
|
|
|
+ let position = geometry.attributes.position.array
|
|
|
+ let normal = geometry.attributes.normal.array
|
|
|
+ let i
|
|
|
+ let up = new THREE.Vector3(0,1,0) , zeroVec = new THREE.Vector3 //up写成z向上居然结果一样
|
|
|
+
|
|
|
+ let positions = [];
|
|
|
+ let normals = [];
|
|
|
+ let newPositions = [];
|
|
|
+ let newIndices = []
|
|
|
+ let groupMaxPointCount = 2000 ;//太多找环会崩
|
|
|
+
|
|
|
+ let minDisSquare = Math.pow(spriteWidth1 * 1.8 , 2 ) //这个数太小就连不上啦 1.65太小
|
|
|
+ let minDot = Math.cos(THREE.Math.degToRad(10))//括号内是最小偏差角度, 20太大。太大的话会将立方体的相邻两面视为一个面。
|
|
|
+
|
|
|
+ //根据相邻点位置和角度是否相近来分组。有风险:两大区域可能因为一个模棱两可中间点连接在一起。
|
|
|
+
|
|
|
+ let closeGroups = []
|
|
|
+ let groupTolerateMaxPoint = 4//组内点<=这个数的最后会被删除
|
|
|
+ let removedCount = 0
|
|
|
+ let useGroupCount = 0
|
|
|
+ let pointDebug = true
|
|
|
+
|
|
|
+
|
|
|
+ for(i=start;i<end;i++){
|
|
|
+ let pos = new THREE.Vector3(position[3*i], position[3*i+1], position[3*i+2] );
|
|
|
+ let nor = new THREE.Vector3(normal[3*i],normal[3*i+1],normal[3*i+2]);
|
|
|
+ pos.nor = nor
|
|
|
+ pos.index = i
|
|
|
+ positions.push(pos)
|
|
|
+ normals.push(nor)
|
|
|
+
|
|
|
+
|
|
|
+ let groups = closeGroups.filter(group=>{
|
|
|
+ if(group.length>groupMaxPointCount)return //满员了
|
|
|
+ var hasClosed = group.some(p=>{
|
|
|
+ var dis = p.distanceToSquared(pos)
|
|
|
+ var dot = p.nor.dot(nor)
|
|
|
+ if(dis<minDisSquare && dot>minDot){
|
|
|
+ //return dis / minDisSquare + (Math.abs(p.nor.x - nor.x) + Math.abs(p.nor.y - nor.y) + Math.abs(p.nor.z - nor.z)) < 1.7
|
|
|
+ return dis / minDisSquare - p.nor.dot(nor) < 0
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return hasClosed
|
|
|
+ })
|
|
|
+
|
|
|
+ if(groups.length == 0){//创建一个新的
|
|
|
+ var newGroup = []
|
|
|
+ closeGroups.push(newGroup)
|
|
|
+ groups = [newGroup]
|
|
|
+ }
|
|
|
+
|
|
|
+ if(groups.length == 1){//直接加入原有的
|
|
|
+ pos.belongTo = groups[0];
|
|
|
+ }else if(groups.length>1){ // comebine多个组成一个
|
|
|
+ let newBigGroup = [];
|
|
|
+ groups.forEach(e=>{
|
|
|
+ newBigGroup.push(...e)
|
|
|
+ let index = closeGroups.indexOf(e);
|
|
|
+ closeGroups.splice(index, 1)
|
|
|
+ })
|
|
|
+ closeGroups.push(newBigGroup)
|
|
|
+ pos.belongTo = newBigGroup
|
|
|
+ newBigGroup.forEach(e=>{e.belongTo = newBigGroup})
|
|
|
+ }
|
|
|
+
|
|
|
+ pos.belongTo.push(pos)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ closeGroups.forEach((points,index)=>{//建造面
|
|
|
+ if(points.length <= groupTolerateMaxPoint ){
|
|
|
+
|
|
|
+
|
|
|
+ /* let sprite = new THREE.Mesh(planeGeo, getPlaneMat(pos.belongTo, true))
|
|
|
+ sprite.lookAt(nor);
|
|
|
+ sprite.position.copy(pos)
|
|
|
+ sprite.scale.set(spriteWidth,spriteWidth,spriteWidth)
|
|
|
+ sprite.name = geometryNode.name+'_index'+i
|
|
|
+ splitSprites.add(sprite)
|
|
|
+ removedCount ++; */
|
|
|
+
|
|
|
+
|
|
|
+ removedCount += points.length;
|
|
|
+ return
|
|
|
+ }
|
|
|
+ useGroupCount ++
|
|
|
+
|
|
|
+ points.sort(function(a,b){
|
|
|
+ return a.index - b.index
|
|
|
+ })
|
|
|
+
|
|
|
+ console.log(`开始解析 ${geometryNode.name} - 第${index}组,总第${points[0].index}个点,组内有${points.length}个点`)
|
|
|
+
|
|
|
+ let planeMat = getPlaneMat(points, true)
|
|
|
+
|
|
|
+
|
|
|
+ if(pointDebug){
|
|
|
+ points.forEach((p,i)=>{
|
|
|
+ var label = new TextSprite({
|
|
|
+ text : index+"-"+i+" ("+p.index+")"+geometryNode.name, dontFixOrient:true,
|
|
|
+ backgroundColor: {r: planeMat.color.r*255, g: planeMat.color.g*255, b: planeMat.color.b*255, a:0.6},
|
|
|
+ });
|
|
|
+ label.lookAt(p.nor);
|
|
|
+ label.position.copy(p)
|
|
|
+ label.scale.set(spriteWidth/3, spriteWidth/3, spriteWidth/3)
|
|
|
+ splitSprites.add(label)
|
|
|
+
|
|
|
+ /* let sprite = new THREE.Mesh(planeGeo,planeMat)
|
|
|
+ sprite.lookAt(p.nor);
|
|
|
+ sprite.position.copy(p)
|
|
|
+ sprite.scale.set(spriteWidth/3,spriteWidth/3,spriteWidth/3)
|
|
|
+ sprite.name = geometryNode.name+'_group'+index+"_"+ i
|
|
|
+ splitSprites.add(sprite) */
|
|
|
+ })
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ var avePos = points.reduce(function(total, currentValue){
|
|
|
+ return total.add(currentValue)
|
|
|
+ }, new THREE.Vector3).multiplyScalar(1/points.length)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ let planeNormals = []
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ {//获得planeNormals
|
|
|
+ //随机找两个距离远的点算normal。 按距离排序后, //抽取若干个点,然后算两两之间的法线,其中距离远的多抽取几个。
|
|
|
+ var sortPoints = points.slice(0).sort(function(a,b){
|
|
|
+ return a.distanceToSquared(avePos) - b.distanceToSquared(avePos)
|
|
|
+ })//从小到大
|
|
|
+ var pickPoints
|
|
|
+
|
|
|
+ var length = sortPoints.length
|
|
|
+ if(length>=7){
|
|
|
+ var ratio = [0.02,0.15,0.4,0.55,0.7,0.86,0.99];
|
|
|
+ var index = ratio.map(e=>Math.round(e * (length-1)))
|
|
|
+ //console.log('index ',index)
|
|
|
+ pickPoints = index.map(e=>sortPoints[e])
|
|
|
+ }else{
|
|
|
+ pickPoints = sortPoints
|
|
|
+ }
|
|
|
+ //console.log('pickPoints', pickPoints)
|
|
|
+ let num = pickPoints.length
|
|
|
+
|
|
|
+ for(let i=0;i<num;i++){//任意一个三角形能算出一个normal
|
|
|
+ for(let j=i+1;j<num;j++){
|
|
|
+ for(let u=j+1;u<num;u++){
|
|
|
+ var p1 = pickPoints[i]
|
|
|
+ var p2 = pickPoints[j]
|
|
|
+ var p3 = pickPoints[u]
|
|
|
+
|
|
|
+ let vec1 = new THREE.Vector3().subVectors(p1,p3)
|
|
|
+ let vec2 = new THREE.Vector3().subVectors(p2,p3)
|
|
|
+ let nor = vec1.cross(vec2).normalize()
|
|
|
+
|
|
|
+ if(planeNormals[0]){
|
|
|
+ if(nor.dot(planeNormals[0])<0)nor.negate() //反向下
|
|
|
+ }
|
|
|
+ //console.log('nor',nor)
|
|
|
+ planeNormals.push(nor)
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ var aveNor = planeNormals.reduce(function(total, currentValue){
|
|
|
+ return total.add(currentValue)
|
|
|
+ }, new THREE.Vector3).normalize()
|
|
|
+
|
|
|
+ console.log('aveNor',aveNor, 'avePos' ,avePos)
|
|
|
+ {
|
|
|
+ var label = new TextSprite({
|
|
|
+ //index+"-"+i+" ("+p.index+")"+geometryNode.name
|
|
|
+
|
|
|
+ text : `我是${index}组 ${geometryNode.name} 中心点`, dontFixOrient:true,
|
|
|
+ backgroundColor: {r: planeMat.color.r*255, g: planeMat.color.g*255, b: planeMat.color.b*255, a:0.6},
|
|
|
+ });
|
|
|
+ label.lookAt(aveNor);
|
|
|
+ label.position.copy(avePos)
|
|
|
+ label.scale.set(spriteWidth, spriteWidth, spriteWidth)
|
|
|
+ splitSprites.add(label)
|
|
|
+ }
|
|
|
+
|
|
|
+ var facePlane = new THREE.Plane().setFromNormalAndCoplanarPoint(aveNor, avePos )
|
|
|
+
|
|
|
+ var coplanarPoints = points.map(p=> facePlane.projectPoint(p, new THREE.Vector3() ))
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ var originPoint0 = coplanarPoints[0].clone()
|
|
|
+ var qua = math.getQuaBetween2Vector(facePlane.normal, new THREE.Vector3(0,0,1), new THREE.Vector3(0,0,1));
|
|
|
+ let points2d = coplanarPoints.map(e=>e.clone().applyQuaternion(qua))
|
|
|
+ let quaInverse = qua.clone().invert()
|
|
|
+
|
|
|
+ //--------------------
|
|
|
+
|
|
|
+ let lines = []
|
|
|
+
|
|
|
+ points2d.forEach((p,j)=>{
|
|
|
+ p.id = j
|
|
|
+ for(let i=0;i<j;i++){
|
|
|
+ if(p.distanceToSquared(points2d[i])<minDisSquare){
|
|
|
+ lines.push({p1:i,p2:j})
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ console.log('points count:',points2d.length, 'lines:',lines)
|
|
|
+ var rings = searchRings({
|
|
|
+ points:points2d,
|
|
|
+ lines,
|
|
|
+ onlyGetOutRing:true,
|
|
|
+ precision: Math.max(spriteWidth1/10, 0.01)
|
|
|
+ })
|
|
|
+ console.log( 'rings:', rings )//mesh间可能重叠 但换上贴图材质应该看不出(但只要searchRings时getSliceLines就不会重叠)
|
|
|
+ if(!rings)return
|
|
|
+ let planeMat2 = planeMat.clone(); planeMat2.opacity = 0.5;
|
|
|
+ var firstPos = points2d[0].clone()
|
|
|
+ firstPos.z = 0 //因为shape只读取了xy,所以位移下, 再算出最终位置,得到差距
|
|
|
+ firstPos.applyQuaternion(quaInverse)
|
|
|
+ var vec = originPoint0.clone().sub(firstPos)
|
|
|
+
|
|
|
+ rings.forEach(ring=>{
|
|
|
+ var shapeGeo = MeshDraw.getShapeGeo(ring.points)
|
|
|
+ var areaPlane = new THREE.Mesh(shapeGeo, planeMat2)
|
|
|
+
|
|
|
+
|
|
|
+ areaPlane.quaternion.copy(quaInverse)
|
|
|
+ areaPlane.position.copy(vec)
|
|
|
+ areaPlane.name = 'areaPlane_'+index
|
|
|
+ splitSprites.add(areaPlane)
|
|
|
+ this.areaPlanes.push(areaPlane)
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ })
|
|
|
+ console.log(geometryNode.name, '中:')
|
|
|
+ console.log('removed point count: ', removedCount/* splitSprites.children.length */)
|
|
|
+ console.log(closeGroups)
|
|
|
+ console.log('comebine mesh Len:', useGroupCount)
|
|
|
+
|
|
|
+
|
|
|
+ /*
|
|
|
+ spritesGeo.setAttribute('position', new THREE.Float32BufferAttribute(new Float32Array(newPositions), 3));
|
|
|
+ spritesGeo.setIndex( newIndices );
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ let sprites = new THREE.Mesh(spritesGeo, getPlaneMat('use'))
|
|
|
+ sprites.name = geometryNode.name
|
|
|
+ sprites.position.copy(sceneNode.position)
|
|
|
+ sprites.rotation.copy(sceneNode.rotation)
|
|
|
+
|
|
|
+ sceneNode.sprites = sprites
|
|
|
+ sprites.pointsNode = sceneNode
|
|
|
+
|
|
|
+ if(geometryNode.level == 0){
|
|
|
+ let root = new THREE.Object3D;
|
|
|
+ root.name = 'spriteNodeRoot'
|
|
|
+
|
|
|
+
|
|
|
+ root.matrixAutoUpdate = false //同pointcloud一样不自动更新,直接使用
|
|
|
+ root.matrix.copy(this.matrix)
|
|
|
+ root.matrixWorld.copy(this.matrixWorld)
|
|
|
+ viewer.scene.scene.add(root)
|
|
|
+ this.spriteNodeRoot = root
|
|
|
+ }
|
|
|
+ this.spriteNodeRoot.add(sprites) */
|
|
|
+
|
|
|
+ console.log('computeTime: ' + (Date.now() - startTime))
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //-----------以下作废======================-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if(geometryNode.level <= -1){
|
|
|
+ let startTime = Date.now()
|
|
|
+ let splitSprites = new THREE.Object3D
|
|
|
+ splitSprites.name = 'splitSprites_'+geometryNode.name
|
|
|
+ splitSprites.matrixAutoUpdate = false //同pointcloud一样不自动更新,直接使用
|
|
|
+ splitSprites.matrix.copy(this.matrix)
|
|
|
+ splitSprites.matrixWorld.copy(this.matrixWorld)
|
|
|
+ viewer.scene.scene.add(splitSprites)
|
|
|
+
|
|
|
+
|
|
|
+ let spritesGeo = new THREE.BufferGeometry();
|
|
|
+
|
|
|
+ let scaleRatio = 1.4 //稍微放大些,填满缝隙
|
|
|
+ let spriteWidth1 = this.material.spacing / Math.pow(2, geometryNode.level)
|
|
|
+ let spriteWidth = spriteWidth1 * scaleRatio
|
|
|
+ console.log('spriteWidth:',spriteWidth)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ const removeChip = true
|
|
|
+
|
|
|
+
|
|
|
+ let geometry = geometryNode.geometry
|
|
|
+ let count = geometry.attributes.position.count
|
|
|
+
|
|
|
+ count = 1000
|
|
|
+
|
|
|
+
|
|
|
+ let position = geometry.attributes.position.array
|
|
|
+ let normal = geometry.attributes.normal.array
|
|
|
+ let i
|
|
|
+ let up = new THREE.Vector3(0,1,0) , zeroVec = new THREE.Vector3 //up写成z向上居然结果一样
|
|
|
+
|
|
|
+ let positions = [];
|
|
|
+ let normals = [];
|
|
|
+ let newPositions = [];
|
|
|
+ //let newNormals = [];
|
|
|
+ let newIndices = []
|
|
|
+ let cornerPoints = [new THREE.Vector3(-1,1,0),new THREE.Vector3(1,1,0),new THREE.Vector3(-1,-1,0),new THREE.Vector3(1,-1,0) ]
|
|
|
+ let indices = [0, 2, 1, 2, 3, 1]
|
|
|
+ cornerPoints.forEach(e=>e.multiplyScalar(spriteWidth/2))
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ let minDisSquare = spriteWidth1 * spriteWidth1 * 1.5
|
|
|
+
|
|
|
+
|
|
|
+ let closeGroups = []
|
|
|
+ let groupTolerateMaxPoint = 4//组内点<=这个数的最后会被删除
|
|
|
+ let removedCount = 0
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ for(i=0;i<count;i++){
|
|
|
+ let pos = new THREE.Vector3(position[3*i], position[3*i+1], position[3*i+2] );
|
|
|
+ let nor = new THREE.Vector3(normal[3*i],normal[3*i+1],normal[3*i+2]);
|
|
|
+ pos.nor = nor
|
|
|
+ positions.push(pos)
|
|
|
+ normals.push(nor)
|
|
|
+
|
|
|
+ if(removeChip){
|
|
|
+ let groups = closeGroups.filter(group=>{
|
|
|
+ var hasClosed = group.some(p=>{
|
|
|
+ var dis = p.distanceToSquared(pos)
|
|
|
+ if(dis<minDisSquare){
|
|
|
+ //return dis / minDisSquare + (Math.abs(p.nor.x - nor.x) + Math.abs(p.nor.y - nor.y) + Math.abs(p.nor.z - nor.z)) < 1.7
|
|
|
+ return dis / minDisSquare - p.nor.dot(nor) < 0
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return hasClosed
|
|
|
+ })
|
|
|
+
|
|
|
+ if(groups.length == 0){//创建一个新的
|
|
|
+ var newGroup = []
|
|
|
+ closeGroups.push(newGroup)
|
|
|
+ groups = [newGroup]
|
|
|
+ }
|
|
|
+
|
|
|
+ if(groups.length == 1){//直接加入原有的
|
|
|
+ pos.belongTo = groups[0];
|
|
|
+ }else if(groups.length>1){ // comebine多个组成一个
|
|
|
+ let newBigGroup = [];
|
|
|
+ groups.forEach(e=>{
|
|
|
+ newBigGroup.push(...e)
|
|
|
+ let index = closeGroups.indexOf(e);
|
|
|
+ closeGroups.splice(index, 1)
|
|
|
+ })
|
|
|
+ closeGroups.push(newBigGroup)
|
|
|
+ pos.belongTo = newBigGroup
|
|
|
+ newBigGroup.forEach(e=>{e.belongTo = newBigGroup})
|
|
|
+ }
|
|
|
+
|
|
|
+ pos.belongTo.push(pos)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ for(i=0;i<count;i++){
|
|
|
+ let pos = positions[i]
|
|
|
+ let nor = normals[i]
|
|
|
+
|
|
|
+
|
|
|
+ if(removeChip){
|
|
|
+ if(pos.belongTo.length <= groupTolerateMaxPoint){
|
|
|
+
|
|
|
+ let sprite = new THREE.Mesh(planeGeo, getPlaneMat(pos.belongTo, true))
|
|
|
+ sprite.lookAt(nor);
|
|
|
+ sprite.position.copy(pos)
|
|
|
+ sprite.scale.set(spriteWidth,spriteWidth,spriteWidth)
|
|
|
+ sprite.name = geometryNode.name+'_index'+i
|
|
|
+ splitSprites.add(sprite)
|
|
|
+ removedCount ++;
|
|
|
+
|
|
|
+ continue
|
|
|
+ }else{
|
|
|
+ /*
|
|
|
+ let sprite = new THREE.Mesh(planeGeo, getPlaneMat(pos.belongTo))
|
|
|
+ sprite.lookAt(nor);
|
|
|
+ sprite.position.copy(pos)
|
|
|
+ sprite.scale.set(spriteWidth/3,spriteWidth/3,spriteWidth/3)
|
|
|
+ sprite.name = geometryNode.name+'_index'+i
|
|
|
+ splitSprites.add(sprite)
|
|
|
+ */
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ let matrix = (new THREE.Matrix4).lookAt( nor, zeroVec, up);
|
|
|
+ matrix.elements[12] = pos.x
|
|
|
+ matrix.elements[13] = pos.y
|
|
|
+ matrix.elements[14] = pos.z
|
|
|
+
|
|
|
+
|
|
|
+ cornerPoints.forEach(p=>{
|
|
|
+ let point = p.clone();
|
|
|
+ point.applyMatrix4(matrix)
|
|
|
+
|
|
|
+ newPositions.push(...point.toArray())
|
|
|
+ //newNormals
|
|
|
+ })
|
|
|
+
|
|
|
+ indices.forEach(index=>{
|
|
|
+ newIndices.push(index + i*4)
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /* closeGroups.forEach(e=>{
|
|
|
+ if(e.length <= groupTolerateMaxPoint )return
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }) */
|
|
|
+
|
|
|
+ console.log('removed count: ', removedCount/* splitSprites.children.length */)
|
|
|
+ console.log(closeGroups)
|
|
|
+ console.log('computeTime: ' + (Date.now() - startTime))
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ spritesGeo.setAttribute('position', new THREE.Float32BufferAttribute(new Float32Array(newPositions), 3));
|
|
|
+ spritesGeo.setIndex( newIndices );
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ let sprites = new THREE.Mesh(spritesGeo, getPlaneMat('use'))
|
|
|
+ sprites.name = geometryNode.name
|
|
|
+ sprites.position.copy(sceneNode.position)
|
|
|
+ sprites.rotation.copy(sceneNode.rotation)
|
|
|
+
|
|
|
+ sceneNode.sprites = sprites
|
|
|
+ sprites.pointsNode = sceneNode
|
|
|
+
|
|
|
+ if(geometryNode.level == 0){
|
|
|
+ let root = new THREE.Object3D;
|
|
|
+ root.name = 'spriteNodeRoot'
|
|
|
+
|
|
|
+
|
|
|
+ root.matrixAutoUpdate = false //同pointcloud一样不自动更新,直接使用
|
|
|
+ root.matrix.copy(this.matrix)
|
|
|
+ root.matrixWorld.copy(this.matrixWorld)
|
|
|
+ viewer.scene.scene.add(root)
|
|
|
+ this.spriteNodeRoot = root
|
|
|
+ }
|
|
|
+ this.spriteNodeRoot.add(sprites)
|
|
|
+ viewer.setObjectLayers(sprites,'sceneObjects')
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //------------------
|
|
|
+ /*
|
|
|
+
|
|
|
+ viewer.scene.pointclouds[0].spriteNodeRoot.traverse(e=>e.material && (e.material = viewer.images360.cube.material))
|
|
|
+ viewer.scene.scene.children[12].visible = false
|
|
|
+
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
updateVisibleBounds () {
|
|
|
let leafNodes = [];
|
|
@@ -1172,6 +1791,7 @@ export class PointCloudOctree extends PointCloudTree {
|
|
|
|
|
|
// 设置点大小
|
|
|
changePointSize(num) {
|
|
|
+
|
|
|
if (num == void 0) {
|
|
|
num = this.temp.pointSize
|
|
|
} else {
|
|
@@ -1193,7 +1813,7 @@ export class PointCloudOctree extends PointCloudTree {
|
|
|
}
|
|
|
|
|
|
|
|
|
- console.log('changePointSize ' + this.dataset_id + ' , num : ' + num + ' , size : ' + this.material.size, this.material.spacing)
|
|
|
+ //console.log('changePointSize ' + this.dataset_id + ' , num : ' + num + ' , size : ' + this.material.size, this.material.spacing)
|
|
|
|
|
|
|
|
|
}
|
|
@@ -1215,16 +1835,17 @@ export class PointCloudOctree extends PointCloudTree {
|
|
|
if(Potree.settings.sizeFitToLevel){//按照点云质量来调整的版本:
|
|
|
let base = this.material.spacing / Math.pow(1.4, this.maxLevel) //随着level提高,点云重叠几率增多
|
|
|
let minBase = this.material.spacing / Math.pow(1.4, this.nodeMaxLevel)
|
|
|
- let ratio = Math.min(1 / base, 1 / minBase / 3) //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高越效果越弱,以减免过度重叠后的亮度。
|
|
|
+ let ratio = Math.min(1 / base, 1 / minBase / 3) //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
|
|
|
this.material.opacity = THREE.Math.clamp(base * ratio * num, 0, 0.999) //到1就不透明了(可能出现一段一样)
|
|
|
}else{
|
|
|
let base = this.material.spacing / Math.pow(1.8, this.maxLevel)
|
|
|
let minBase = this.material.spacing / Math.pow(1.8, this.nodeMaxLevel)
|
|
|
//console.log(1 / base, 1 / minBase / 6)
|
|
|
- let ratio = Math.min(1 / base, 1 / minBase / 9) //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高越效果越弱,以减免过度重叠后的亮度。
|
|
|
+ let ratio = Math.min(1 / base, 1 / minBase / 6) //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
|
|
|
this.material.opacity = THREE.Math.clamp(base * ratio * num, 0, 0.999) //到1就不透明了(可能出现一段一样)
|
|
|
+
|
|
|
}
|
|
|
-
|
|
|
+ //缺点:防止颜色过亮主要是相机离远时,当在漫游点处由于离点云太近,可能会导致高质量点云看起来很暗。
|
|
|
}
|
|
|
//console.log('changePointOpacity ' + this.dataset_id + ', num : ' + num + ' , opacity : ' + this.material.opacity) //检查是否做到了低质量时num==opacity,中质量opacity稍小于num,高质量更小
|
|
|
|
|
@@ -1285,6 +1906,32 @@ export class PointCloudOctree extends PointCloudTree {
|
|
|
|
|
|
|
|
|
|
|
|
+window.searchOutRing = function(points){
|
|
|
+ var points = [{x:0,y:0},{x:1,y:1},{x:0,y:1},{x:1,y:0},{x:2,y:1},{x:1,y:2},{x:1,y:3},{x:2,y:3},
|
|
|
+ {x:3,y:1},{x:3,y:2},{x:0,y:2},{x:0,y:3},{x:2,y:0},{x:-1,y:0},{x:-1,y:1},{x:-2,y:1},{x:3,y:3},
|
|
|
+ {x:3,y:0},{x:2,y:-1},{x:0,y:-1},{x:1,y:0.5},{x:2,y:0.5}, ].map((e,index)=>{
|
|
|
+ var a = new THREE.Vector2().copy(e)
|
|
|
+ a.id = index;
|
|
|
+ return a
|
|
|
+ })
|
|
|
+ var lines = []
|
|
|
+ var minDis = 2*2
|
|
|
+ points.forEach((p,j)=>{
|
|
|
+ for(let i=0;i<j;i++){
|
|
|
+ if(p.distanceToSquared(points[i])<minDis){
|
|
|
+ lines.push({p1:i,p2:j})
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+ searchRings({
|
|
|
+ points,
|
|
|
+ lines,
|
|
|
+ onlyGetOutRing:true
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|
|
|
|