|
@@ -0,0 +1,248 @@
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+import math from "./math.js";
|
|
|
+
|
|
|
+class DepthTexSampler {
|
|
|
+
|
|
|
+ constructor(edlRenderer){
|
|
|
+ this.needDraw = true
|
|
|
+ this.edlRenderer = edlRenderer
|
|
|
+ this.renderer = viewer.renderer
|
|
|
+ this.renderTarget = new THREE.WebGLRenderTarget(1,1, {
|
|
|
+ format: THREE.RGBAFormat,
|
|
|
+ type: THREE.UnsignedByteType, //默认THREE.UnsignedByteType THREE.FloatType UnsignedShortType UnsignedInt248Type
|
|
|
+ //depthBuffer:false,
|
|
|
+ /* minFilter: THREE.NearestFilter,
|
|
|
+ magFilter: THREE.NearestFilter,
|
|
|
+ format: THREE.RGBAFormat,
|
|
|
+ type: THREE.FloatType,
|
|
|
+ depthBuffer:false, */
|
|
|
+ //depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
|
|
|
+ });
|
|
|
+ /* document.getElementsByTagName('body')[0].appendChild(canvas);
|
|
|
+ canvas.style.position = 'fixed';
|
|
|
+ canvas.style.width = '1024px';
|
|
|
+ canvas.style.top = canvas.style.left = 0
|
|
|
+ canvas.style['z-index'] = 100
|
|
|
+ */
|
|
|
+ this.recoverToScreenMat = edlRenderer.recoverToScreenMat.clone();
|
|
|
+ delete this.recoverToScreenMat.defines.useDepth
|
|
|
+ this.recoverToScreenMat.needsUpdate = true
|
|
|
+
|
|
|
+ viewer.addEventListener('pointcloud_changed',()=>{
|
|
|
+ this.needDraw = true
|
|
|
+ })
|
|
|
+ viewer.addEventListener('camera_changed',(e)=>{
|
|
|
+
|
|
|
+ this.needDraw = true
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ convertToLinear(zValue) { //zValue越接近相机越大, 0-1
|
|
|
+ var z = zValue * 2.0 - 1.0; // -1 to 1
|
|
|
+ return (2.0 * this.near * this.far) / (this.far + this.near - z * (this.far - this.near));
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ perspectiveDepthToViewZ(zValue){
|
|
|
+ return -( this.near * this.far ) / ( ( this.far - this.near ) * zValue - this.far );
|
|
|
+ }
|
|
|
+ //convertToLinear和perspectiveDepthToViewZ结果好像差不多
|
|
|
+
|
|
|
+ /* viewZToPerspectiveDepth(viewZ, near, far ) {
|
|
|
+ return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );
|
|
|
+ } */
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //改写成只渲染depthTex的一部分(改贴图的offset和scale)
|
|
|
+ getDepth(depthTex, x, y) {//根据图片像素获取深度值
|
|
|
+ if(this.needDraw){
|
|
|
+ if(this.renderTarget.width != depthTex.image.width || this.renderTarget.height != depthTex.image.height)this.renderTarget.setSize(depthTex.image.width, depthTex.image.height)
|
|
|
+ /* let oldTarget = this.renderer.getRenderTarget()
|
|
|
+ this.renderer.setRenderTarget(this.renderTarget) */
|
|
|
+
|
|
|
+ this.recoverToScreenMat.uniforms.tDiffuse.value = depthTex
|
|
|
+ this.recoverToScreenMat.needsUpdate = true
|
|
|
+ Potree.Utils.screenPass.render(viewer.renderer, this.recoverToScreenMat, this.renderTarget); //目前耗时有点久
|
|
|
+ //this.renderer.setRenderTarget(oldTarget)
|
|
|
+ this.needDraw = false
|
|
|
+ }
|
|
|
+
|
|
|
+ //var r = this.context.getImageData(x, y, 1, 1).data;
|
|
|
+
|
|
|
+ let pixelCount = 1;
|
|
|
+ let buffer = new Uint8Array(4 * pixelCount);
|
|
|
+ this.renderer.readRenderTargetPixels(this.renderTarget, x, this.renderTarget.height-y, 1, 1, buffer);
|
|
|
+ //目前得到的r值不太准确,256个层级本身就很少,而near很小far很大时,分层就朝近处移动,远处很不准。
|
|
|
+
|
|
|
+
|
|
|
+ let depth = this.convertToLinear(buffer[0] / 255, this.near, this.far)
|
|
|
+ console.log('buffer', buffer, x,y, depth)
|
|
|
+ return depth
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ sample( viewport , mouse, dir ) {//通过和skybox的intersect得到真实的intersect的位置
|
|
|
+
|
|
|
+
|
|
|
+ let rtEdl = this.edlRenderer.getRtEDL(viewport)
|
|
|
+ if(!rtEdl)return 'unsupport'
|
|
|
+ let depthTex = rtEdl.depthTexture
|
|
|
+
|
|
|
+ this.near = viewport.camera.near, this.far = viewport.camera.far
|
|
|
+ let distance = this.getDepth(depthTex, mouse.x, mouse.y)
|
|
|
+ console.log('dis', distance )
|
|
|
+
|
|
|
+
|
|
|
+ let location = new THREE.Vector3
|
|
|
+ let normal
|
|
|
+ dir = dir || viewer.inputHandler.getMouseDirection().direction //这里可能有问题: 该viewport不一定是在viewer上,不能用viewer.inputHandler
|
|
|
+ let origin = viewport.view.position
|
|
|
+
|
|
|
+ location.copy(dir).multiplyScalar(distance).add(origin);
|
|
|
+ /*
|
|
|
+ //
|
|
|
+ if (!distance){
|
|
|
+ if(uv.y > 0.75){//漫游点底部识别不到的区域,给一个地板高度
|
|
|
+ //let height = origin.distanceTo(currentPano.floorPosition);
|
|
|
+ const margin = 0.1
|
|
|
+ distance = (currentPano.floorPosition.z - origin.z - margin) / dir.z
|
|
|
+ location.copy(dir).multiplyScalar(distance).add(origin);
|
|
|
+ let normal = new THREE.Vector3(0,0,1)
|
|
|
+
|
|
|
+ return {location, normal, distance}
|
|
|
+ }
|
|
|
+ else return !1; //应该是天空或模型外 , 因为很少有漫游点的地方还拍不到地板
|
|
|
+ }
|
|
|
+
|
|
|
+ //this.mainDepth = depth
|
|
|
+
|
|
|
+ location.copy(dir).multiplyScalar(distance).add(origin);
|
|
|
+
|
|
|
+ if(!onlyPos){
|
|
|
+
|
|
|
+ var pL = this.getNearbyPoint(origin, uv, -1, 0)
|
|
|
+ , pR = this.getNearbyPoint(origin, uv, 1, 0)
|
|
|
+ , pB = this.getNearbyPoint(origin, uv, 0, -1)
|
|
|
+ , pT = this.getNearbyPoint(origin, uv, 0, 1);
|
|
|
+
|
|
|
+ normal = this.planeFit(dir,location, pL,pR,pB,pT )
|
|
|
+ } */
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //console.log('normal',normal)
|
|
|
+
|
|
|
+
|
|
|
+ normal = new THREE.Vector3(1,0,0)
|
|
|
+
|
|
|
+
|
|
|
+ return {location, normal, distance}
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ getNearbyPoint( origin, uv, x, y) { //获取附近的若干像素距离的点
|
|
|
+ let uv2 = uv.clone()
|
|
|
+ uv2.x += x/(this.canvas.width-1);
|
|
|
+ uv2.x = this.clampUV(uv2.x)
|
|
|
+
|
|
|
+ uv2.y += y/(this.canvas.height-1);
|
|
|
+ uv2.y = this.clampUV(uv2.y)
|
|
|
+
|
|
|
+ /* if(uv2.x < 0 || uv2.y < 0 || uv2.x > 1 || uv2.y > 1){
|
|
|
+ console.log('will nan')
|
|
|
+ } */
|
|
|
+
|
|
|
+ let dir = math.getDirFromUV(uv2)//从uv获取到方向
|
|
|
+ dir.applyMatrix4(viewer.images360.currentPano.panoMatrix2)
|
|
|
+ let depth = this.getDepth(uv2.x, uv2.y);
|
|
|
+ /* if(Math.abs(depth - this.mainDepth) > 0.3){
|
|
|
+ console.log('Math.abs(depth - this.mainDepth) > 0.3')
|
|
|
+ } */
|
|
|
+
|
|
|
+ //let dir = new THREE.Vector3().subVectors(intersect.point, origin).normalize()
|
|
|
+ let position = new THREE.Vector3().copy(dir).multiplyScalar(depth).add(origin);
|
|
|
+
|
|
|
+ //console.log('getNearbyPoint', uv2, depth, dir, position )
|
|
|
+
|
|
|
+ return position
|
|
|
+ }
|
|
|
+
|
|
|
+ clampUV(v){
|
|
|
+ return (v + 1) % 1; // 使输出在 0-1
|
|
|
+ }
|
|
|
+
|
|
|
+ planeFit(dir, position, pL,pR,pB,pT ) {//求平均法线
|
|
|
+ let normal = new THREE.Vector3
|
|
|
+
|
|
|
+
|
|
|
+ let plane = new THREE.Plane;
|
|
|
+ function addNormal(p1, p2) {//根据临接的四个点,分别求法线,然后法线相加能得到平均法线
|
|
|
+ if(!p1 || !p2)return
|
|
|
+ plane.setFromCoplanarPoints(position, p1, p2)
|
|
|
+
|
|
|
+ //console.log('normalSub', plane.normal)
|
|
|
+
|
|
|
+ normal.addScaledVector(plane.normal, dir.dot(plane.normal) < 0 ? 1 : -1)//根据面的朝向判断加还是减
|
|
|
+ }
|
|
|
+ addNormal(pL, pB)
|
|
|
+ addNormal(pL, pT)
|
|
|
+ addNormal(pR, pB)
|
|
|
+ addNormal(pR, pT)
|
|
|
+
|
|
|
+ if(0 !== normal.x || 0 !== normal.y || 0 !== normal.z){
|
|
|
+ normal.normalize()
|
|
|
+ //console.log(normal)
|
|
|
+ return normal
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /* 四个面拼成一个菱形 */
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+ /*
|
|
|
+ 注:
|
|
|
+
|
|
|
+
|
|
|
+ 由于有时候获取intersect需要知道是哪个点云,所以还是不能用这个。如加测量线。
|
|
|
+
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+export default DepthTexSampler
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|