Parcourir la source

pick improvements

- ensure lines & points are at least 1 pixel big
- look around center pixel in a spiral for hits
Alexander Rose il y a 3 ans
Parent
commit
e840059a38

+ 15 - 1
src/mol-canvas3d/passes/pick.ts

@@ -11,6 +11,7 @@ import { WebGLContext } from '../../mol-gl/webgl/context';
 import { GraphicsRenderVariant } from '../../mol-gl/webgl/render-item';
 import { RenderTarget } from '../../mol-gl/webgl/render-target';
 import { Vec3 } from '../../mol-math/linear-algebra';
+import { spiral2d } from '../../mol-math/misc';
 import { decodeFloatRGB, unpackRGBAToDepth } from '../../mol-util/float-packing';
 import { Camera, ICamera } from '../camera';
 import { StereoCamera } from '../camera/stereo';
@@ -88,6 +89,7 @@ export class PickPass {
 
         this.groupPickTarget.bind();
         this.renderVariant(renderer, camera, scene, helper, 'pickGroup');
+        // printTexture(this.webgl, this.groupPickTarget.texture, { id: 'group' })
 
         this.depthPickTarget.bind();
         this.renderVariant(renderer, camera, scene, helper, 'depth');
@@ -111,6 +113,8 @@ export class PickHelper {
     private pickHeight: number
     private halfPickWidth: number
 
+    private spiral: [number, number][]
+
     private setupBuffers() {
         const bufferSize = this.pickWidth * this.pickHeight * 4;
         if (!this.objectBuffer || this.objectBuffer.length !== bufferSize) {
@@ -138,6 +142,9 @@ export class PickHelper {
 
             this.setupBuffers();
         }
+
+        // TODO: make spiral size configurable
+        this.spiral = spiral2d(Math.ceil(this.pickScale * 5));
     }
 
     private syncBuffers() {
@@ -193,7 +200,7 @@ export class PickHelper {
         this.dirty = false;
     }
 
-    identify(x: number, y: number, camera: Camera | StereoCamera): PickData | undefined {
+    private identifyInternal(x: number, y: number, camera: Camera | StereoCamera): PickData | undefined {
         const { webgl, pickScale } = this;
         if (webgl.isContextLost) return;
 
@@ -252,6 +259,13 @@ export class PickHelper {
         return { id: { objectId, instanceId, groupId }, position };
     }
 
+    identify(x: number, y: number, camera: Camera | StereoCamera): PickData | undefined {
+        for (const d of this.spiral) {
+            const pickData = this.identifyInternal(x + d[0], y + d[1], camera);
+            if (pickData) return pickData;
+        }
+    }
+
     constructor(private webgl: WebGLContext, private renderer: Renderer, private scene: Scene, private helper: Helper, private pickPass: PickPass, viewport: Viewport) {
         this.setViewport(viewport.x, viewport.y, viewport.width, viewport.height);
     }

+ 1 - 0
src/mol-gl/shader/lines.vert.ts

@@ -105,6 +105,7 @@ void main(){
     #else
         linewidth = size * uPixelRatio;
     #endif
+    linewidth = max(1.0, linewidth);
 
     // adjust for linewidth
     offset *= linewidth;

+ 1 - 0
src/mol-gl/shader/points.vert.ts

@@ -36,6 +36,7 @@ void main(){
     #else
         gl_PointSize = size * uPixelRatio;
     #endif
+    gl_PointSize = max(1.0, gl_PointSize);
 
     gl_Position = uProjection * mvPosition;
 

+ 25 - 1
src/mol-math/misc.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -37,4 +37,28 @@ export function absMax(...values: number[]) {
 /** Length of an arc with angle in radians */
 export function arcLength(angle: number, radius: number) {
     return angle * radius;
+}
+
+/** Create an outward spiral of given `radius` on a 2d grid */
+export function spiral2d(radius: number) {
+    let x = 0;
+    let y = 0;
+    const delta = [0, -1];
+    const size = radius * 2 + 1;
+    const halfSize = size / 2;
+    const out: [number, number][] = [];
+
+    for (let i = Math.pow(size, 2); i > 0; --i) {
+        if ((-halfSize < x && x <= halfSize) && (-halfSize < y && y <= halfSize)) {
+            out.push([x, y]);
+        }
+
+        if (x === y || (x < 0 && x === -y) || (x > 0 && x === 1 - y)) {
+            [delta[0], delta[1]] = [-delta[1], delta[0]]; // change direction
+        }
+
+        x += delta[0];
+        y += delta[1];
+    }
+    return out;
 }