123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- import * as THREE from "../../../libs/three.js/build/three.module.js";
- import Common from '../utils/Common.js'
-
- export class ViewerBase extends THREE.EventDispatcher{
- constructor(domElement, args = {}){
- super()
- this.name = args.name
- this.renderArea = domElement
- this.oldResolution = new THREE.Vector2()
- this.oldResolution2 = new THREE.Vector2()
-
- this.screenSizeInfo = {
- W:0, H:0, pixelRatio:1 , windowWidth:0, windowHeight:0
- }
-
- this.initContext(args);
-
-
- this.addEventListener('content_changed', ()=>{//画面改变,需要渲染
- this.needRender = true
- //console.log('needRender')
- })
-
-
- }
-
-
-
-
-
- initContext(args){
- //console.log(`initializing three.js ${THREE.REVISION}`);
- let width = this.renderArea.clientWidth;
- let height = this.renderArea.clientHeight;
- let contextAttributes = {
- alpha: true,//支持透明
- depth: true,
- stencil: false,
- antialias: !!args.antialias,
- preserveDrawingBuffer: args.preserveDrawingBuffer || false ,
- powerPreference: "high-performance",
- };
- let canvas = document.createElement("canvas");
-
- let context = canvas.getContext('webgl', contextAttributes ); //不用webgl2是因为有的写法在webgl2不支持 如gl_FragDepthEXT
-
- this.renderer = new THREE.WebGLRenderer({
- premultipliedAlpha: false,
- canvas: canvas,
- context: context,
- });
-
- this.renderer.sortObjects = true; //原先false 打开了renderOrder才奏效
- //this.renderer.setSize(width, height);
- this.renderer.autoClear = args.autoClear || false;
- //args.clearColor = args.clearColor || '#aa0033'
- args.clearColor && this.renderer.setClearColor(args.clearColor)
- this.renderArea.appendChild(this.renderer.domElement);
- this.renderer.domElement.tabIndex = '2222';
- this.renderer.domElement.style.position = 'absolute';
- this.renderer.domElement.addEventListener('mousedown', () => {
- this.renderer.domElement.focus();
- });
- //this.renderer.domElement.focus();
- // NOTE: If extension errors occur, pass the string into this.renderer.extensions.get(x) before enabling
- // enable frag_depth extension for the interpolation shader, if available
- let gl = this.renderer.getContext();
-
-
- gl.getExtension('EXT_frag_depth');
- gl.getExtension('WEBGL_depth_texture');
- gl.getExtension('WEBGL_color_buffer_float'); // Enable explicitly for more portability, EXT_color_buffer_float is the proper name in WebGL 2
-
- if(gl.createVertexArray == null){
- let extVAO = gl.getExtension('OES_vertex_array_object');
- if(!extVAO){
- throw new Error("OES_vertex_array_object extension not supported");
- }
- gl.createVertexArray = extVAO.createVertexArrayOES.bind(extVAO);
- gl.bindVertexArray = extVAO.bindVertexArrayOES.bind(extVAO);
- }
-
-
-
-
-
-
-
-
- /* let oldClear = gl.clear;
- gl.clear = (bits)=>{
- console.error('clear')
- }
- */
-
- }
-
-
-
-
- updateScreenSize(o={}) { //有可能需要让viewport来判断,当窗口大小不变但viewport大小变时
-
- var render = false, ratio, w, h;
- //记录应当render的大小
- if (o.width != void 0 && o.height != void 0) {
- w = o.width
- h = o.height
- render = true
- ratio = 1
- }else {
- w = this.renderArea.clientWidth;
- h = this.renderArea.clientHeight
-
-
- if(w !== this.screenSizeInfo.W || h !== this.screenSizeInfo.H || o.forceUpdateSize || this.screenSizeInfo.pixelRatio != window.devicePixelRatio){
- this.screenSizeInfo.W = w
- this.screenSizeInfo.H = h
- render = true
- this.screenSizeInfo.pixelRatio = window.devicePixelRatio //如果player放在小窗口了,也要监测devicePixelRatio,因为缩放时client宽高不会改变
- //config.isMobile ? (ratio = Math.min(window.devicePixelRatio, 2)) : (ratio = window.devicePixelRatio)
- ratio = window.devicePixelRatio
- }
- }
- if (render) {
- this.setSize(w, h, ratio, o.forTarget );
- }
- }
-
-
- setSize(width, height, devicePixelRatio, onlyForTarget){
- //console.log('setSize', width)
- if(!onlyForTarget){//onlyForTarget表示不更改当前renderer,只是为了rendertarget才要改变viewport
- this.renderer.setPixelRatio(devicePixelRatio)
- this.renderer.setSize(width, height ); // resize之后会自动clear(似乎因为setScissor ),所以一定要立刻绘制,所以setSize要在cameraChanged、update之前
-
- }
-
- //this.composer && this.composer.setSize(width, height);
-
- if(this.viewports){
- this.viewports.forEach((view,i)=>{
- //if(!view.active)return
-
- var width_ = width * view.width
- var height_ = height * view.height
-
- view.setResolution(Math.ceil(width_), Math.ceil(height_), width, height ) //本来应该是floor,但是这样奇数时会少一个像素,导致向左移一个像素且宽度少1。现在则多绘制1个像素,超出的1个像素应该不会绘制出来(但不知道其他地方是否有偏差,比如pick时)
-
-
- if(height_ == 0)return //avoid NAN
- let aspect = width_ / height_; //camera的参数精确些,不用视口的归整的resolution像素值,否则hasChange无法为true, 导致canvasResize了但map没update从而闪烁
- view.camera.aspect = aspect;
-
- if(view.camera.type == "OrthographicCamera"){
-
- /* //不改宽度 同4dkk
- var heightHalf = view.camera.right / aspect
- view.camera.top = heightHalf
- view.camera.bottom = -heightHalf */
- //高宽都改 使大小不随视口大小改变 navvis (直接和视口大小一致即可,通过zoom来定大小)
-
- view.camera.left = -width_/2
- view.camera.right = width_/2
- view.camera.bottom = -height_/2;
- view.camera.top = height_/2
-
-
- }else{
-
-
- }
-
- view.camera.updateProjectionMatrix();
- })
- }
-
-
- if(!onlyForTarget){//因为onlyForTarget不传递devicePixelRatio所以不发送了
- this.dispatchEvent('viewerResize')
- this.viewports.forEach(e=>{
- this.ifEmitResize({viewport:e, deviceRatio:devicePixelRatio})
- })
- }
-
- }
-
- ifEmitResize(e){//切换viewport渲染时, 若这些viewport大小不同就发送一次, 通知一些材质更新resolution。
- //console.log('ifEmitResize',e.viewport.name,e.viewport.resolution2 )
- if(!e.viewport.resolution.equals(this.oldResolution)||!e.viewport.resolution2.equals(this.oldResolution2)){
- this.dispatchEvent($.extend(e, {type:'resize'}))
- this.oldResolution.copy(e.viewport.resolution)
- this.oldResolution2.copy(e.viewport.resolution2)
- }
- }
-
-
-
- cameraChanged() {//判断相机是否改变
- var changed = false;
- /* if(this.needRender){
- this.needRender = false
- return true
- } */
-
-
- for(let i=0,j=this.viewports.length;i<j;i++){
- let viewport = this.viewports[i]
- let changeInfo = viewport.cameraChanged()
- if(changeInfo.changed){
- changed = true
- //if(!this.changeTime ||this.changeTime<100){
- this.dispatchEvent({
- type: "camera_changed",
- camera: viewport.camera,
- viewport ,
- changeInfo
- })
- //this.changeTime = (this.changeTime || 0) +1
- //}
- viewport.needRender = true //直接写这咯
- if(changeInfo.resolutionChanged){
- this.ifEmitResize({viewport}) //for map
- }
-
- }
- }
- return changed
- }
-
-
-
-
-
-
- makeScreenshot( size, viewports, compressRatio){//暂时不要指定viewports渲染,但也可以
-
-
- let {width, height} = size;
-
-
-
-
- /* let oldBudget = Potree.pointBudget;
- Potree.pointBudget = Math.max(10 * 1000 * 1000, 2 * oldBudget);
- let result = Potree.updatePointClouds(this.scene.pointclouds, camera, size );
- Potree.pointBudget = oldBudget;
-
-
- this.dispatchEvent({ //resize everything such as lines targets
- type: 'resize',
- resolution: new THREE.Vector2(width,height),
- });*/
-
- let target = new THREE.WebGLRenderTarget(width, height, {
- format: THREE.RGBAFormat,
- });
-
-
- this.setSize(width, height,1,true)
-
- this.render({
- target ,
- //camera ,
- viewports: viewports || this.viewports,
- screenshot : true,
- width ,
- height,
- resize :true //需要resize
- });
- let dataUrl = Potree.Utils.renderTargetToDataUrl(target, width, height, this.renderer, compressRatio)
-
-
- /* let pixelCount = width * height;
- let buffer = new Uint8Array(4 * pixelCount);
- this.renderer.readRenderTargetPixels(target, 0, 0, width, height, buffer);
- let dataUrl = Potree.Utils.pixelsArrayToDataUrl(buffer, width, height, compressRatio) */
-
- target.dispose();
-
- //resize back
- //this.updateScreenSize({forceUpdateSize:true})
-
- return {
- width,
- height,
- dataUrl
- };
- }
-
-
-
- dispose(scene=this.scene){
-
- scene.clear();
- this.renderer.dispose()
- this.renderer.forceContextLoss()
- let gl = this.renderer.getContext();
- gl.getExtension("WEBGL_lose_context") && gl.getExtension("WEBGL_lose_context").loseContext()
- this.renderArea.removeChild(this.renderer.domElement)
- this.dispatchEvent('dispose')
- }
-
- }
|