summaryrefslogtreecommitdiff
path: root/graphics/asymptote/webgl/gl.js
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/asymptote/webgl/gl.js')
-rw-r--r--graphics/asymptote/webgl/gl.js171
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);
}