|
@@ -0,0 +1,255 @@
|
|
|
+import * as THREE from 'three'
|
|
|
+
|
|
|
+export const limitForHeight = {
|
|
|
+ view: null,
|
|
|
+ limitH: null,
|
|
|
+ maxLimitH:null,
|
|
|
+ analyseLayerView: null,
|
|
|
+ analyseLayer: null,
|
|
|
+ externalRenderers:null,
|
|
|
+ drawVertices: [],
|
|
|
+ setup(context) {
|
|
|
+ this.renderer = new THREE.WebGLRenderer({
|
|
|
+ context: context.gl,
|
|
|
+ //premultipliedAlpha: false,
|
|
|
+ //antialias: true,
|
|
|
+ //logarithmicDepthBuffer: true,
|
|
|
+ //polygonOffset: true,
|
|
|
+ //polygonoffset 是一个比较常见的消除 z-fighting 的设置项。
|
|
|
+ // 在 threejs 中我们可以设置 material 的 polygonoffset 属性来达到启用的目的。
|
|
|
+ // 其原理是在渲染的时候,将模型的订单稍微向靠近或远离相机的方向做一定的偏移,从而错开两个靠近的面的目的。
|
|
|
+ alpha: true
|
|
|
+ })
|
|
|
+ this.renderer.shadowMap.enabled = true
|
|
|
+ this.renderer.shadowMap.type = THREE.PCFSoftShadowMap
|
|
|
+ //设置设备像素比,可以避免HiDPI设备上绘图模糊
|
|
|
+ this.renderer.setPixelRatio(window.devicePixelRatio)
|
|
|
+ //设置视口大小和三维场景的大小一样
|
|
|
+ this.renderer.setViewport(0, 0, this.view.width, this.view.height)
|
|
|
+ // 防止Three.js清除ArcGIS JS API提供的缓冲区
|
|
|
+ this.renderer.autoClearDepth = false // 定义renderer是否清除深度缓存
|
|
|
+ this.renderer.autoClearStencil = false // 定义renderer是否清除模板缓存
|
|
|
+ this.renderer.autoClearColor = false // 定义renderer是否清除颜色缓存
|
|
|
+ //ArcGIS JS API渲染自定义离屏缓冲区,而不是默认的帧缓冲区。
|
|
|
+ //我们必须将这段代码注入到Three.js运行时中,以便绑定这些缓冲区而不是默认的缓冲区。
|
|
|
+ var originalSetRenderTarget = this.renderer.setRenderTarget.bind(this.renderer)
|
|
|
+ this.renderer.setRenderTarget = function (target) {
|
|
|
+ originalSetRenderTarget(target)
|
|
|
+ this.state.viewport(new THREE.Vector4(0, 0, this.view.width, this.view.height))
|
|
|
+ if (target == null) {
|
|
|
+ context.bindRenderTarget()
|
|
|
+ }
|
|
|
+ }.bind(this.renderer)
|
|
|
+
|
|
|
+ //支持裁切
|
|
|
+ this.renderer.localClippingEnabled = true
|
|
|
+
|
|
|
+ this.scene = new THREE.Scene()
|
|
|
+ this.camera = new THREE.PerspectiveCamera()
|
|
|
+ this.camera.far = 10000000
|
|
|
+ this.ambient = new THREE.AmbientLight(0xffffff, 1)
|
|
|
+ this.scene.add(this.ambient)
|
|
|
+ this.sun = new THREE.DirectionalLight(0xffffff, 0.5)
|
|
|
+ this.scene.add(this.sun)
|
|
|
+
|
|
|
+ this.start(context)
|
|
|
+ context.resetWebGLState()
|
|
|
+ },
|
|
|
+ render(context) {
|
|
|
+ var cam = context.camera
|
|
|
+ this.camera.position.set(cam.eye[0], cam.eye[1], cam.eye[2])
|
|
|
+ this.camera.up.set(cam.up[0], cam.up[1], cam.up[2])
|
|
|
+ this.camera.lookAt(new THREE.Vector3(cam.center[0], cam.center[1], cam.center[2]))
|
|
|
+ // 投影矩阵可以直接复制
|
|
|
+ this.camera.projectionMatrix.fromArray(cam.projectionMatrix)
|
|
|
+
|
|
|
+ //更新操作
|
|
|
+ let that = this
|
|
|
+ if (
|
|
|
+ this.meshGroup &&
|
|
|
+ this.meshGroup.children.length > 0 &&
|
|
|
+ this.meshGroup.children[0].material.uniforms
|
|
|
+ ) {
|
|
|
+ this.meshGroup.children.forEach(function (mesh) {
|
|
|
+ mesh.material.uniforms.limit.value = that.limitH
|
|
|
+ mesh.material.uniforms.maxLimit.value = that.maxLimitH
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ this.renderer.state.reset()
|
|
|
+ //threejs 127版本后 需要加上
|
|
|
+ context.bindRenderTarget()
|
|
|
+ this.renderer.render(this.scene, this.camera)
|
|
|
+ this.externalRenderers.requestRender(this.view)
|
|
|
+ context.resetWebGLState()
|
|
|
+ },
|
|
|
+ async start(context) {
|
|
|
+ if (this.analyseLayerView) {
|
|
|
+ let clipPanels = this.createClipPlane()
|
|
|
+ let meshMaterial = this.analysisRender()
|
|
|
+ meshMaterial.clippingPlanes = clipPanels
|
|
|
+ this.meshGroup = new THREE.Group()
|
|
|
+ debugger
|
|
|
+ let posGroup = await this.analyseLayerView.getFeatureInfo()
|
|
|
+ this.createGeometry(posGroup)
|
|
|
+ this.meshGroup &&
|
|
|
+ this.meshGroup.children.forEach(function (mesh) {
|
|
|
+ mesh.material = meshMaterial
|
|
|
+ })
|
|
|
+ this.scene.add(this.meshGroup)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ createGeometry(posGroup) {
|
|
|
+ posGroup.forEach((object_pos) => {
|
|
|
+ var geometry = new THREE.BufferGeometry()
|
|
|
+ geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(object_pos), 3))
|
|
|
+ geometry.computeBoundingBox()
|
|
|
+ geometry.computeBoundingSphere()
|
|
|
+ geometry.computeVertexNormals()
|
|
|
+
|
|
|
+ const positions = geometry.attributes.position
|
|
|
+ const normals = geometry.attributes.normal
|
|
|
+ let uvs = []
|
|
|
+ // 计算UV坐标
|
|
|
+ for (let i = 0; i < positions.count; i++) {
|
|
|
+ const normal = new THREE.Vector3(
|
|
|
+ normals.getX(i),
|
|
|
+ normals.getY(i),
|
|
|
+ normals.getZ(i)
|
|
|
+ ).normalize()
|
|
|
+
|
|
|
+ const position = new THREE.Vector3(positions.getX(i), positions.getY(i), positions.getZ(i))
|
|
|
+ uvs.push((normal.x + 1) / 2, (normal.y + 1) / 2)
|
|
|
+ }
|
|
|
+ geometry.setAttribute('uv', new THREE.BufferAttribute(Float32Array.from(uvs), 2, false))
|
|
|
+ var material = new THREE.MeshPhongMaterial({
|
|
|
+ color: 'red',
|
|
|
+ transparent: false,
|
|
|
+ // opacity: 0.3,
|
|
|
+ polygonOffset: true,
|
|
|
+ polygonOffsetFactor: -0.5,
|
|
|
+ polygonOffsetUnits: -0.5
|
|
|
+ })
|
|
|
+ var mesh = new THREE.Mesh(geometry, material)
|
|
|
+ mesh.updateMatrix()
|
|
|
+ this.meshGroup.add(mesh)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ //根据多边形点创建裁切面
|
|
|
+ createClipPlane() {
|
|
|
+ let clipPanels = []
|
|
|
+ debugger
|
|
|
+ this.drawVertices.push(this.drawVertices[0])
|
|
|
+ for (let k = 0; k < this.drawVertices.length - 1; k++) {
|
|
|
+ let point1 = this.drawVertices[k]
|
|
|
+ let point2 = this.drawVertices[k + 1]
|
|
|
+ let base1 = []
|
|
|
+ let base2 = []
|
|
|
+ let top1 = []
|
|
|
+ this.externalRenderers.toRenderCoordinates(
|
|
|
+ this.view,
|
|
|
+ [point1[0], point1[1], 0],
|
|
|
+ 0,
|
|
|
+ this.view.spatialReference,
|
|
|
+ base1,
|
|
|
+ 0,
|
|
|
+ 1
|
|
|
+ )
|
|
|
+ this.externalRenderers.toRenderCoordinates(
|
|
|
+ this.view,
|
|
|
+ [point2[0], point2[1], 0],
|
|
|
+ 0,
|
|
|
+ this.view.spatialReference,
|
|
|
+ base2,
|
|
|
+ 0,
|
|
|
+ 1
|
|
|
+ )
|
|
|
+ this.externalRenderers.toRenderCoordinates(
|
|
|
+ this.view,
|
|
|
+ [point1[0], point1[1], point1[2] + 1000],
|
|
|
+ 0,
|
|
|
+ this.view.spatialReference,
|
|
|
+ top1,
|
|
|
+ 0,
|
|
|
+ 1
|
|
|
+ )
|
|
|
+ let plane = new THREE.Plane()
|
|
|
+ let p1_1 = new THREE.Vector3(base1[0], base1[1], base1[2])
|
|
|
+ let p2_1 = new THREE.Vector3(top1[0], top1[1], top1[2])
|
|
|
+ let p3_1 = new THREE.Vector3(base2[0], base2[1], base2[2])
|
|
|
+ plane.setFromCoplanarPoints(p1_1, p2_1, p3_1)
|
|
|
+ clipPanels.push(plane)
|
|
|
+ }
|
|
|
+ return clipPanels
|
|
|
+ },
|
|
|
+ analysisRender() {
|
|
|
+ //let texture = new THREE.TextureLoader().load('images/view.png');
|
|
|
+ let material = new THREE.MeshBasicMaterial({
|
|
|
+ //map: texture,
|
|
|
+ color: '#FF0000',
|
|
|
+ opacity: 0.8,
|
|
|
+ transparent: true,
|
|
|
+ side: THREE.DoubleSide,
|
|
|
+ depthTest: false
|
|
|
+ })
|
|
|
+ material.onBeforeCompile = function (shader, renderer) {
|
|
|
+ debugger
|
|
|
+ //声明用到的变量和常量
|
|
|
+ const getFoot = `
|
|
|
+ uniform mat4 cameraMatrix;
|
|
|
+ uniform mat4 projectionMatrixInverse;
|
|
|
+ varying float depth;
|
|
|
+ varying vec2 depthUv;
|
|
|
+ //varying vec2 vUv;
|
|
|
+ varying vec4 vPosition;
|
|
|
+ #include <common>
|
|
|
+ `
|
|
|
+ const begin_vertex = `
|
|
|
+ #include <worldpos_vertex>
|
|
|
+ vPosition= modelMatrix * vec4(transformed, 1.0 );
|
|
|
+ `
|
|
|
+ const height_vary = `
|
|
|
+ uniform float opacity;
|
|
|
+ uniform float limit;
|
|
|
+ uniform float maxLimit;
|
|
|
+ uniform float baseHeight;
|
|
|
+ varying vec4 vPosition;
|
|
|
+ float getHeight(vec3 point){
|
|
|
+ float distR = length(point);
|
|
|
+ float height=distR-6378137.0;
|
|
|
+ return height-0.1;
|
|
|
+ }
|
|
|
+ `
|
|
|
+ const height_frag = `
|
|
|
+ vec3 outgoingLight = reflectedLight.indirectDiffuse;
|
|
|
+ float ph=getHeight(vPosition.xyz);
|
|
|
+ if(ph>=limit&&ph<=maxLimit){
|
|
|
+ //gl_FragColor = vec4( outgoingLight, diffuseColor.a );
|
|
|
+ }else{
|
|
|
+ diffuseColor.a=0.0;
|
|
|
+ }
|
|
|
+ `
|
|
|
+ shader.vertexShader = shader.vertexShader.replace('#include <common>', getFoot)
|
|
|
+ shader.vertexShader = shader.vertexShader.replace('#include <worldpos_vertex>', begin_vertex)
|
|
|
+ shader.fragmentShader = shader.fragmentShader.replace('uniform float opacity;', height_vary)
|
|
|
+
|
|
|
+ shader.fragmentShader = shader.fragmentShader.replace(
|
|
|
+ 'vec3 outgoingLight = reflectedLight.indirectDiffuse;',
|
|
|
+ height_frag
|
|
|
+ )
|
|
|
+ //shader.fragmentShader = shader.fragmentShader.replace('gl_FragColor = vec4( outgoingLight, diffuseColor.a );', height_frag)
|
|
|
+ shader.uniforms.limit = {
|
|
|
+ value: this.limitH
|
|
|
+ }
|
|
|
+ shader.uniforms.maxLimit = {
|
|
|
+ value: this.maxLimitH
|
|
|
+ }
|
|
|
+ shader.uniforms.baseHeight = {
|
|
|
+ value: 0.0
|
|
|
+ }
|
|
|
+ material.uniforms = shader.uniforms
|
|
|
+ }
|
|
|
+ material.needsUpdate = true
|
|
|
+ return material
|
|
|
+ }
|
|
|
+}
|