Skip to content

Commit

Permalink
fix ClusterBundle edge type and add picking
Browse files Browse the repository at this point in the history
  • Loading branch information
Manfred Cheung committed Aug 22, 2023
1 parent 0811545 commit 22d777c
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 5 deletions.
13 changes: 12 additions & 1 deletion src/graph/edges/bundle/ClusterBundle.data.vs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ layout(location=4) in uint aSourceColor;
layout(location=5) in uint aTargetColor;
layout(location=6) in uvec2 aHyperEdgeStats;
layout(location=7) in uint aIndex;
layout(location=8) in uvec4 aPickingColor;

uniform sampler2D uGraphPoints;

Expand All @@ -17,8 +18,16 @@ out vec3 vControl;
flat out uint vSourceColor;
flat out uint vTargetColor;
out vec2 vColorMix;
flat out uvec4 vPickingColor;

#pragma glslify: valueForIndex = require(../../../renderer/shaders/valueForIndex.glsl)
// manual import from ../../../renderer/shaders/valueForIndex.glsl
// to avoid uvec4 pragma error
vec4 valueForIndex(sampler2D tex, int index) {
int texWidth = textureSize(tex, 0).x;
int col = index % texWidth;
int row = index / texWidth;
return texelFetch(tex, ivec2(col, row), 0);
}

void main() {
vec4 source = valueForIndex(uGraphPoints, int(aSourceIndex));
Expand Down Expand Up @@ -94,4 +103,6 @@ void main() {
vTargetColor = aTargetColor;

vColorMix = vec2(float(aIndex) * 0.25, float(aIndex + 1u) * 0.25);

vPickingColor = aPickingColor;
}
1 change: 1 addition & 0 deletions src/graph/edges/bundle/ClusterBundle.picking.fs.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#pragma glslify: import(../path/CurvedPath.picking.fs.glsl)
55 changes: 51 additions & 4 deletions src/graph/edges/bundle/ClusterBundle.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import edgeVS from './ClusterBundle.vs.glsl';
import edgeFS from './ClusterBundle.fs.glsl';
import pickingFS from './ClusterBundle.picking.fs.glsl';
import dataVS from './ClusterBundle.data.vs.glsl';

import {App, DrawCall, PicoGL, Program, VertexArray, VertexBuffer} from 'picogl';
Expand All @@ -14,7 +15,8 @@ import {
} from '../../../renderer/Renderable';
import {Edges} from '../Edges';
import {GraphPoints} from '../../../data/GraphPoints';
import {PickingManager} from '../../../UX/picking/PickingManager';
import {PickingColors, PickingEvent, PickingManager} from '../../../UX/picking/PickingManager';
import { MouseCallback } from 'src/UX/mouse/MouseHandler';
import {GraferContext} from '../../../renderer/GraferContext';

export interface ClusterBundleEdgeData {
Expand All @@ -26,8 +28,10 @@ export interface ClusterBundleEdgeData {
sourceColor?: GraferInputColor,
targetColor?: GraferInputColor,
hyperEdgeStats?: [number, number],
pickingColor?: number | [number, number, number, number];
}

const pickingColorNoOpMapping = (): null => null;
const kClusterBundleEdgeNoOpMapping = (): null => null;
export const kClusterBundleEdgeMappings: DataMappings<ClusterBundleEdgeData & { index: number[] }> = {
id: (entry: ClusterBundleEdgeData, i) => 'id' in entry ? entry.id : i,
Expand All @@ -39,6 +43,7 @@ export const kClusterBundleEdgeMappings: DataMappings<ClusterBundleEdgeData & {
targetColor: (entry: ClusterBundleEdgeData) => 'targetColor' in entry ? entry.targetColor : 0, // first registered color
hyperEdgeStats: kClusterBundleEdgeNoOpMapping, // this will be replaced in `computeMappings`
index: () => [0, 1, 2],
pickingColor: pickingColorNoOpMapping,
};

export const kClusterBundleEdgeDataTypes: GLDataTypes<ClusterBundleEdgeData & { index: number[] }> = {
Expand All @@ -50,6 +55,7 @@ export const kClusterBundleEdgeDataTypes: GLDataTypes<ClusterBundleEdgeData & {
targetColor: PicoGL.UNSIGNED_INT,
hyperEdgeStats: [PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT],
index: PicoGL.UNSIGNED_INT,
pickingColor: [PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT],
};

export const kGLClusterBundleEdgeTypes = {
Expand All @@ -59,6 +65,7 @@ export const kGLClusterBundleEdgeTypes = {
sourceColor: PicoGL.UNSIGNED_INT,
targetColor: PicoGL.UNSIGNED_INT,
colorMix: [PicoGL.FLOAT, PicoGL.FLOAT],
pickingColor: [PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT],
} as const;
export type GLClusterBundleEdgeTypes = typeof kGLClusterBundleEdgeTypes;

Expand All @@ -68,6 +75,11 @@ export class ClusterBundle extends Edges<ClusterBundleEdgeData, GLClusterBundleE
protected program: Program;
protected drawCall: DrawCall;

protected pickingProgram: Program;
protected pickingDrawCall: DrawCall;
protected pickingColors: PickingColors;
protected pickingHandler: MouseCallback;

protected verticesVBO: VertexBuffer;
protected edgesVAO: VertexArray;

Expand Down Expand Up @@ -100,6 +112,8 @@ export class ClusterBundle extends Edges<ClusterBundleEdgeData, GLClusterBundleE
);
}

this.pickingHandler = this.handlePickingEvent.bind(this);

this.verticesVBO = context.createVertexBuffer(PicoGL.FLOAT, 2, new Float32Array(segmentVertices));
this.edgesVAO = context.createVertexArray().vertexAttributeBuffer(0, this.verticesVBO);
this.configureTargetVAO(this.edgesVAO);
Expand All @@ -108,19 +122,32 @@ export class ClusterBundle extends Edges<ClusterBundleEdgeData, GLClusterBundleE
this.program = context.createProgram(shaders.vs, shaders.fs);
this.drawCall = context.createDrawCall(this.program, this.edgesVAO).primitive(PicoGL.TRIANGLE_STRIP);

const pickingShaders = this.getPickingShaders();
this.pickingProgram = context.createProgram(pickingShaders.vs, pickingShaders.fs);
this.pickingDrawCall = context.createDrawCall(this.pickingProgram, this.edgesVAO).primitive(PicoGL.TRIANGLE_STRIP);

this.compute(context, {
uGraphPoints: this.dataTexture,
});

// printDataGL(context, this.targetVBO, data.length, kGLClusterBundleEdgeTypes);

this.pickingManager.on(PickingManager.events.hoverOn, this.pickingHandler);
this.pickingManager.on(PickingManager.events.hoverOff, this.pickingHandler);
this.pickingManager.on(PickingManager.events.click, this.pickingHandler);

this.localUniforms.uSegments = segments;
}

public destroy(): void {
// TODO: Implement destroy method
}

protected ingestData(context: App, data: unknown[], mappings: Partial<DataMappings<ClusterBundleEdgeData>>): void {
this.pickingColors = this.pickingManager.allocatePickingColors(data.length);
super.ingestData(context, data, mappings);
}

public render(context:App, mode: RenderMode, uniforms: RenderUniforms): void {
setDrawCallUniforms(this.drawCall, uniforms);
setDrawCallUniforms(this.drawCall, this.localUniforms);
Expand All @@ -129,7 +156,10 @@ export class ClusterBundle extends Edges<ClusterBundleEdgeData, GLClusterBundleE

switch (mode) {
case RenderMode.PICKING:
// this.pickingDrawCall.draw();
setDrawCallUniforms(this.pickingDrawCall, uniforms);
setDrawCallUniforms(this.pickingDrawCall, this.localUniforms);
this.pickingDrawCall.uniform('uPicking', true);
this.pickingDrawCall.draw();
break;

default:
Expand All @@ -148,7 +178,7 @@ export class ClusterBundle extends Edges<ClusterBundleEdgeData, GLClusterBundleE
protected getPickingShaders(): RenderableShaders {
return {
vs: edgeVS,
fs: null, // pickingFS,
fs: pickingFS,
};
}

Expand All @@ -163,7 +193,7 @@ export class ClusterBundle extends Edges<ClusterBundleEdgeData, GLClusterBundleE
protected getDataShader(): DataShader {
return {
vs: dataVS,
varyings: [ 'vSource', 'vTarget', 'vControl', 'vSourceColor', 'vTargetColor', 'vColorMix' ],
varyings: [ 'vSource', 'vTarget', 'vControl', 'vSourceColor', 'vTargetColor', 'vColorMix', 'vPickingColor' ],
};
}

Expand Down Expand Up @@ -207,6 +237,16 @@ export class ClusterBundle extends Edges<ClusterBundleEdgeData, GLClusterBundleE
}
this.hyperEdgeStats.set(key, count + 1);
entry.hyperEdgeStats[0] = count;

this.idArray.push(entry.id);

const indexStart = 4 * i;
entry.pickingColor = [
this.pickingColors.colors[indexStart],
this.pickingColors.colors[indexStart + 1],
this.pickingColors.colors[indexStart + 2],
this.pickingColors.colors[indexStart + 3],
];
};

const cb2 = (i: number, entry: ClusterBundleEdgeData): void => {
Expand All @@ -219,4 +259,11 @@ export class ClusterBundle extends Edges<ClusterBundleEdgeData, GLClusterBundleE
cb2,
];
}

protected handlePickingEvent(event: PickingEvent, colorID: number): void {
if (this.picking && this.pickingColors.map.has(colorID)) {
const id = this.idArray[this.pickingColors.map.get(colorID)];
this.emit(event, id);
}
}
}

0 comments on commit 22d777c

Please sign in to comment.