diff options
Diffstat (limited to 'graphics/asymptote/webgl/gl.js')
-rw-r--r-- | graphics/asymptote/webgl/gl.js | 171 |
1 files changed, 92 insertions, 79 deletions
diff --git a/graphics/asymptote/webgl/gl.js b/graphics/asymptote/webgl/gl.js index a7cf6a5862..f05312dec5 100644 --- a/graphics/asymptote/webgl/gl.js +++ b/graphics/asymptote/webgl/gl.js @@ -5,12 +5,14 @@ let Centers=[]; // Array of billboard centers let Background=[1,1,1,1]; // Background color let canvasWidth,canvasHeight; +let canvasWidth0,canvasHeight0; // Initial values let absolute=false; let b,B; // Scene min,max bounding box corners (3-tuples) let angle; // Field of view angle let Zoom0; // Initial zoom +let zoom0; // Adjusted initial zoom let viewportmargin; // Margin around viewport (2-tuple) let viewportshift=[0,0]; // Viewport shift (for perspective projection) @@ -41,16 +43,16 @@ let maxMaterials; // Limit on number of materials allowed in shader let halfCanvasWidth,halfCanvasHeight; let pixel=0.75; // Adaptive rendering constant. +let zoomRemeshFactor=1.5; // Zoom factor before remeshing let FillFactor=0.1; let Zoom; -let maxViewportWidth=window.innerWidth; -let maxViewportHeight=window.innerHeight; +let maxViewportWidth; +let maxViewportHeight; const windowTrim=10; -let resizeStep=1.2; -let lastzoom; +let lastZoom; let H; // maximum camera view half-height let third=1/3; @@ -1871,15 +1873,20 @@ class Triangles extends Geometry { } -function home() +function redraw() { - mat4.identity(rotMat); initProjection(); setProjection(); remesh=true; draw(); } +function home() +{ + mat4.identity(rotMat); + redraw(); +} + let positionAttribute=0; let normalAttribute=1; let materialAttribute=2; @@ -2141,13 +2148,13 @@ function rotateScene(lastX,lastY,rawX,rawY,factor) if(lastX == rawX && lastY == rawY) return; let [angle,axis]=arcball([lastX,-lastY],[rawX,-rawY]); - mat4.fromRotation(T,2*factor*ArcballFactor*angle/lastzoom,axis); + mat4.fromRotation(T,2*factor*ArcballFactor*angle/Zoom,axis); mat4.multiply(rotMat,T,rotMat); } function shiftScene(lastX,lastY,rawX,rawY) { - let zoominv=1/lastzoom; + let zoominv=1/Zoom; shift.x += (rawX-lastX)*zoominv*halfCanvasWidth; shift.y -= (rawY-lastY)*zoominv*halfCanvasHeight; } @@ -2178,8 +2185,10 @@ function capzoom() if(Zoom <= minzoom) Zoom=minzoom; if(Zoom >= maxzoom) Zoom=maxzoom; - if(Zoom != lastzoom) remesh=true; - lastzoom=Zoom; + if(zoomRemeshFactor*Zoom < lastZoom || Zoom > zoomRemeshFactor*lastZoom) { + remesh=true; + lastZoom=Zoom; + } } function zoomImage(diff) @@ -2211,9 +2220,8 @@ function arcball(oldmouse,newmouse) let oldMouse=normMouse(oldmouse); let newMouse=normMouse(newmouse); let Dot=dot(oldMouse,newMouse); - if(Dot > 1) Dot=1; - else if(Dot < -1) Dot=-1; - return [Math.acos(Dot),unit(cross(oldMouse,newMouse))] + let angle=Dot > 1 ? 0 : Dot < -1 ? pi : Math.acos(Dot); + return [angle,unit(cross(oldMouse,newMouse))] } /** @@ -2342,6 +2350,13 @@ function handleKey(event) } } +function setZoom() +{ + capzoom(); + setProjection(); + draw(); +} + function handleMouseWheel(event) { event.preventDefault(); @@ -2351,10 +2366,8 @@ function handleMouseWheel(event) } else { Zoom /= zoomFactor; } - capzoom(); - setProjection(); - draw(); + setZoom(); } function handleMouseMove(event) @@ -2560,9 +2573,9 @@ function draw() function setDimensions(width,height,X,Y) { let Aspect=width/height; - let zoominv=1/lastzoom; - let xshift=(X/width+viewportshift[0])*lastzoom; - let yshift=(Y/height+viewportshift[1])*lastzoom; + let zoominv=1/Zoom; + let xshift=(X/width+viewportshift[0])*Zoom; + let yshift=(Y/height+viewportshift[1])*Zoom; if (orthographic) { let xsize=B[0]-b[0]; @@ -2612,7 +2625,7 @@ function initProjection() center.x=center.y=0; center.z=0.5*(b[2]+B[2]); - lastzoom=Zoom=Zoom0; + lastZoom=Zoom=zoom0; viewParam.zmin=b[2]; viewParam.zmax=B[2]; @@ -2638,6 +2651,7 @@ function setCanvas() size2=Math.hypot(canvasWidth,canvasHeight); halfCanvasWidth=0.5*canvas.width; halfCanvasHeight=0.5*canvas.height; + ArcballFactor=1+8*Math.hypot(viewportmargin[0],viewportmargin[1])/size2; } function setsize(w,h) @@ -2655,75 +2669,53 @@ function setsize(w,h) canvasHeight=h; setCanvas(); setViewport(); - home(); -} - -function expand() -{ - setsize(canvasWidth*resizeStep+0.5,canvasHeight*resizeStep+0.5); -} -function shrink() -{ - setsize(Math.max((canvasWidth/resizeStep+0.5),1), - Math.max((canvasHeight/resizeStep+0.5),1)); + setProjection(); + remesh=true; } -let pixelShader,materialShader,colorShader,transparentShader; - -function webGLInit() +function resize() { - canvas=document.getElementById("Asymptote"); - embedded=window.top.document != document; - - initGL(); + zoom0=Zoom0; if(absolute && !embedded) { - canvasWidth *= window.devicePixelRatio; - canvasHeight *= window.devicePixelRatio; + canvasWidth=canvasWidth0*window.devicePixelRatio; + canvasHeight=canvasHeight0*window.devicePixelRatio; } else { - let Aspect=canvasWidth/canvasHeight; + let Aspect=canvasWidth0/canvasHeight0; canvasWidth=Math.max(window.innerWidth-windowTrim,windowTrim); canvasHeight=Math.max(window.innerHeight-windowTrim,windowTrim); if(!orthographic && canvasWidth < canvasHeight*Aspect) - Zoom0 *= canvasWidth/(canvasHeight*Aspect); + zoom0 *= canvasWidth/(canvasHeight*Aspect); } canvas.width=canvasWidth; canvas.height=canvasHeight; - setCanvas(); + let maxViewportWidth=window.innerWidth; + let maxViewportHeight=window.innerHeight; - ArcballFactor=1+8*Math.hypot(viewportmargin[0],viewportmargin[1])/size2; + viewportshift[0] /= zoom0; + viewportshift[1] /= zoom0; - viewportshift[0] /= Zoom0; - viewportshift[1] /= Zoom0; - - gl.enable(gl.BLEND); - gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA); - gl.enable(gl.DEPTH_TEST); - gl.enable(gl.SCISSOR_TEST); - - setViewport(); - home(); + setsize(canvasWidth,canvasHeight); + redraw(); +} - canvas.onmousedown=handleMouseDown; - document.onmouseup=handleMouseUpOrTouchEnd; - document.onmousemove=handleMouseMove; - canvas.onkeydown=handleKey; +function expand() +{ + Zoom *= zoomFactor; + setZoom(); +} - if(!embedded) - enableZoom(); - canvas.addEventListener("touchstart",handleTouchStart,false); - canvas.addEventListener("touchend",handleMouseUpOrTouchEnd,false); - canvas.addEventListener("touchcancel",handleMouseUpOrTouchEnd,false); - canvas.addEventListener("touchleave",handleMouseUpOrTouchEnd,false); - canvas.addEventListener("touchmove",handleTouchMove,false); - document.addEventListener("keydown",handleKey,false); +function shrink() +{ + Zoom /= zoomFactor; + setZoom(); } -let listen=false; +let pixelShader,materialShader,colorShader,transparentShader; class Align { constructor(center,dir) { @@ -3107,16 +3099,37 @@ function tube(v,w,CenterIndex,MaterialIndex,Min,Max,core) function webGLStart() { - if(window.innerWidth == 0 || window.innerHeight == 0) { - if(!listen) { - listen=true; - window.addEventListener("resize",webGLStart,false); - } - } else { - if(listen) { - window.removeEventListener("resize",webGLStart,false); - listen=false; - } - webGLInit(); - } + canvas=document.getElementById("Asymptote"); + embedded=window.top.document != document; + + initGL(); + + gl.enable(gl.BLEND); + gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA); + gl.enable(gl.DEPTH_TEST); + gl.enable(gl.SCISSOR_TEST); + + canvas.onmousedown=handleMouseDown; + document.onmouseup=handleMouseUpOrTouchEnd; + document.onmousemove=handleMouseMove; + canvas.onkeydown=handleKey; + + if(!embedded) + enableZoom(); + canvas.addEventListener("touchstart",handleTouchStart,false); + canvas.addEventListener("touchend",handleMouseUpOrTouchEnd,false); + canvas.addEventListener("touchcancel",handleMouseUpOrTouchEnd,false); + canvas.addEventListener("touchleave",handleMouseUpOrTouchEnd,false); + canvas.addEventListener("touchmove",handleTouchMove,false); + document.addEventListener("keydown",handleKey,false); + + canvasWidth0=canvasWidth; + canvasHeight0=canvasHeight; + + mat4.identity(rotMat); + + if(window.innerWidth != 0 && window.innerHeight != 0) + resize(); + + window.addEventListener("resize",resize,false); } |