Skip to content
Snippets Groups Projects
Commit 71590f3a authored by Alexander Rose's avatar Alexander Rose
Browse files

basic picking works

parent 2676e03f
No related branches found
No related tags found
No related merge requests found
......@@ -99,13 +99,14 @@ type ViewportState = {
showLogo: boolean,
aspectRatio: number,
images: { [k: string]: ImageData }
info: string
}
export class Viewport extends View<ViewportController, ViewportState, { noWebGl?: boolean, showLogo?: boolean, aspectRatio: number }> {
export class Viewport extends View<ViewportController, ViewportState, { noWebGl?: boolean, showLogo?: boolean, aspectRatio: number, info: string }> {
private container: HTMLDivElement | null = null;
private canvas: HTMLCanvasElement | null = null;
private defaultBg = { r: 1, g: 1, b: 1 }
state: ViewportState = { noWebGl: false, showLogo: true, images: {}, aspectRatio: 1 };
state: ViewportState = { noWebGl: false, showLogo: true, images: {}, aspectRatio: 1, info: '' };
componentDidMount() {
if (!this.canvas || !this.container || !this.controller.context.initStage(this.canvas, this.container)) {
......@@ -121,6 +122,10 @@ export class Viewport extends View<ViewportController, ViewportState, { noWebGl?
})
})
viewer.identified.subscribe(info => {
this.setState({ info })
})
viewer.didDraw.subscribe(() => {
// this.setState({ imageData: viewer.getImageData() })
viewer.pick()
......@@ -163,6 +168,18 @@ export class Viewport extends View<ViewportController, ViewportState, { noWebGl?
</div>
{this.state.showLogo ? <Logo /> : void 0}
<ViewportControls controller={this.controller} />
<div
style={{
position: 'absolute',
top: 10,
left: 10,
padding: 10,
color: 'lightgrey',
background: 'rgba(0, 0, 0, 0.2)'
}}
>
{this.state.info}
</div>
<div
style={{
position: 'absolute',
......
vec4 encodeFloatRGBA(float v) {
vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * v;
enc = fract(enc);
enc -= enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);
return enc;
vec4 encodeFloatRGBA(in float value) {
value = clamp(value, 0., 16777216.);
vec3 c = vec3(0.);
c.b = mod(value, 256.);
value = floor(value/256.);
c.g = mod(value, 256.);
value = floor(value/256.);
c.r = mod(value, 256.);
return vec4(c/255., 1.);
}
#pragma glslify: export(encodeFloatRGBA)
\ No newline at end of file
#pragma glslify: encodeFloatRGBA = require(../utils/encode-float-rgba.glsl)
#define MAX_ID 16777216.0
vec4 encodeIdRGBA( const in float v ) {
return encodeFloatRGBA(((v + 1.0) / MAX_ID));
vec4 encodeIdRGBA(const in float v) {
return encodeFloatRGBA(v + 1.0);
}
#pragma glslify: export(encodeIdRGBA)
\ No newline at end of file
......@@ -6,7 +6,7 @@
import { BehaviorSubject } from 'rxjs';
import { Vec3, Mat4, EPSILON, Vec4 } from 'mol-math/linear-algebra'
import { Vec3, Mat4, EPSILON } from 'mol-math/linear-algebra'
import InputObserver from 'mol-util/input/input-observer'
import * as SetUtils from 'mol-util/set'
import Renderer, { RendererStats } from 'mol-gl/renderer'
......@@ -22,6 +22,23 @@ import { createRenderTarget } from 'mol-gl/webgl/render-target';
import Scene from 'mol-gl/scene';
import { RenderVariant } from 'mol-gl/webgl/render-item';
function decodeFloatRGBA(r: number, g: number, b: number) {
r = Math.floor(r)
g = Math.floor(g)
b = Math.floor(b)
return r * 256 * 256 + g * 256 + b
}
function decodeIdRGBA(r: number, g: number, b: number) {
return decodeFloatRGBA(r, g, b) - 1
}
interface PickingId {
objectId: number
instanceId: number
elementId: number
}
interface Viewer {
center: (p: Vec3) => void
......@@ -40,6 +57,7 @@ interface Viewer {
identify: (x: number, y: number) => void
reprCount: BehaviorSubject<number>
identified: BehaviorSubject<string>
didDraw: BehaviorSubject<number>
handleResize: () => void
......@@ -67,13 +85,17 @@ namespace Viewer {
export function create(canvas: HTMLCanvasElement, container: Element): Viewer {
const reprMap = new Map<Representation<any>, Set<RenderObject>>()
const reprCount = new BehaviorSubject(0)
const identified = new BehaviorSubject('')
const startTime = performance.now()
const didDraw = new BehaviorSubject(0)
const input = InputObserver.create(canvas)
input.resize.subscribe(handleResize)
input.move.subscribe(({x, y}) => identify(x, y))
input.move.subscribe(({x, y}) => {
const p = identify(x, y)
identified.next(`Object: ${p.objectId}, Instance: ${p.instanceId}, Element: ${p.elementId}`)
})
const camera = PerspectiveCamera.create({
near: 0.1,
......@@ -99,7 +121,7 @@ namespace Viewer {
const scene = Scene.create(ctx)
const renderer = Renderer.create(ctx, camera)
const pickScale = 1 // 1 / 4
const pickScale = 1 / 4
const pickWidth = Math.round(canvas.width * pickScale)
const pickHeight = Math.round(canvas.height * pickScale)
const objectPickTarget = createRenderTarget(ctx, pickWidth, pickHeight)
......@@ -142,29 +164,26 @@ namespace Viewer {
window.requestAnimationFrame(() => animate())
}
const decodeFactors = Vec4.create(1, 1/255, 1/65025, 1/16581375)
function decodeFloatRGBA(rgba: Vec4) {
return Vec4.dot(rgba, decodeFactors);
}
function identify (x: number, y: number) {
function identify (x: number, y: number): PickingId {
const buffer = new Uint8Array(4)
y = canvas.height - y // flip y
const xp = Math.round(x * pickScale)
const yp = Math.round(y * pickScale)
console.log('position', x, y, xp, yp)
const buffer = new Uint8Array(4)
objectPickTarget.bind()
ctx.readPixels(xp, yp, 1, 1, buffer)
const objectId = decodeIdRGBA(buffer[0], buffer[1], buffer[2])
instancePickTarget.bind()
ctx.readPixels(xp, yp, 1, 1, buffer)
const instanceId = decodeIdRGBA(buffer[0], buffer[1], buffer[2])
elementPickTarget.bind()
ctx.readPixels(xp, yp, 1, 1, buffer)
console.log('identify', buffer[0], buffer[1], buffer[2], buffer[3])
const v = Vec4.create(buffer[0], buffer[1], buffer[2], buffer[3])
const d = decodeFloatRGBA(v)
console.log(d)
console.log(d * 16777216)
const elementId = decodeIdRGBA(buffer[0], buffer[1], buffer[2])
ctx.unbindFramebuffer()
ctx.readPixels(x, y, 1, 1, buffer)
console.log('color', buffer[0], buffer[1], buffer[2], buffer[3])
return { objectId, instanceId, elementId }
}
handleResize()
......@@ -242,6 +261,7 @@ namespace Viewer {
}
},
reprCount,
identified,
didDraw,
get input() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment