Skip to content

Commit

Permalink
Add picking for StraightPath edge type
Browse files Browse the repository at this point in the history
  • Loading branch information
Manfred Cheung committed Aug 22, 2023
1 parent 1ca8c22 commit 0811545
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/graph/edges/path/CurvedPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import dataVS from './CurvedPath.data.vs.glsl';

import {App, DrawCall, PicoGL, Program, VertexArray, VertexBuffer} from 'picogl';
import {GraferInputColor} from '../../../renderer/colors/ColorRegistry';
import {DataMappings, DataShader, kDataMappingFlatten, printDataGL} from '../../../data/DataTools';
import {DataMappings, DataShader, kDataMappingFlatten} from '../../../data/DataTools';
import {
GLDataTypes,
RenderableShaders,
Expand All @@ -26,7 +26,7 @@ export interface CurvedPathEdgeData {
control: number | number[];
sourceColor?: GraferInputColor,
targetColor?: GraferInputColor,
pickingColor?: [number, number, number, number];
pickingColor?: number | [number, number, number, number];
}

const pickingColorNoOpMapping = (): null => null;
Expand Down
4 changes: 4 additions & 0 deletions src/graph/edges/path/StraightPath.data.vs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ layout(location=1) in uint aTargetIndex;
layout(location=2) in uvec2 aControl;
layout(location=3) in uint aSourceColor;
layout(location=4) in uint aTargetColor;
layout(location=5) in uvec4 aPickingColor;

uniform sampler2D uGraphPoints;

Expand All @@ -13,6 +14,7 @@ flat out uint fTarget;
flat out uint fSourceColor;
flat out uint fTargetColor;
flat out vec2 fColorMix;
flat out uvec4 fPickingColor;

void main() {
fSource = aSourceIndex;
Expand All @@ -22,4 +24,6 @@ void main() {
fTargetColor = aTargetColor;

fColorMix = vec2(float(aControl[0]) / float(aControl[1]), float(aControl[0] + 1u) / float(aControl[1]));

fPickingColor = aPickingColor;
}
10 changes: 10 additions & 0 deletions src/graph/edges/path/StraightPath.picking.fs.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#version 300 es
precision highp float;

flat in vec4 fPickingColor;

out vec4 fragColor;

void main() {
fragColor = fPickingColor;
}
55 changes: 51 additions & 4 deletions src/graph/edges/path/StraightPath.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import edgeVS from './StraightPath.vs.glsl';
import edgeFS from './StraightPath.fs.glsl';
import pickingFS from './StraightPath.picking.fs.glsl';
import dataVS from './StraightPath.data.vs.glsl';

import {CurvedPathEdgeData, GLCurvedPathEdgeTypes, kCurvedPathEdgeMappings} from './CurvedPath';
Expand All @@ -15,14 +16,16 @@ import {DataMappings, DataShader, kDataMappingFlatten} from '../../../data/DataT
import {BasicEdgeData, Edges} from '../Edges';
import {GraferContext} from '../../../renderer/GraferContext';
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';

export const kStraightPathEdgeDataTypes: GLDataTypes<CurvedPathEdgeData> = {
source: PicoGL.UNSIGNED_INT,
target: PicoGL.UNSIGNED_INT,
control: [PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT],
sourceColor: PicoGL.UNSIGNED_INT,
targetColor: PicoGL.UNSIGNED_INT,
pickingColor: [PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT, PicoGL.UNSIGNED_INT],
};

export const kGLStraightPathEdgeTypes = {
Expand All @@ -31,13 +34,19 @@ export const kGLStraightPathEdgeTypes = {
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 GLStraightPathEdgeTypes = typeof kGLStraightPathEdgeTypes;

export class StraightPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeTypes> {
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 All @@ -57,24 +66,52 @@ export class StraightPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeType
1, 1,
]));

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

this.edgesVAO = context.createVertexArray().vertexAttributeBuffer(0, this.verticesVBO);
this.configureTargetVAO(this.edgesVAO);

const shaders = this.getDrawShaders();
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, kGLStraightPathEdgeTypes);
this.pickingManager.on(PickingManager.events.hoverOn, this.pickingHandler);
this.pickingManager.on(PickingManager.events.hoverOff, this.pickingHandler);
this.pickingManager.on(PickingManager.events.click, this.pickingHandler);
}

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

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

protected packDataCB(): any {
return (index, entry): void => {
this.idArray.push(entry.id);

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

public render(context:App, mode: RenderMode, uniforms: RenderUniforms): void {
this.configureRenderContext(context, mode);

Expand All @@ -83,7 +120,10 @@ export class StraightPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeType

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 @@ -102,7 +142,7 @@ export class StraightPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeType
protected getPickingShaders(): RenderableShaders {
return {
vs: edgeVS,
fs: null, // pickingFS,
fs: pickingFS,
};
}

Expand All @@ -117,7 +157,7 @@ export class StraightPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeType
protected getDataShader(): DataShader {
return {
vs: dataVS,
varyings: [ 'fSource', 'fTarget', 'fSourceColor', 'fTargetColor', 'fColorMix' ],
varyings: [ 'fSource', 'fTarget', 'fSourceColor', 'fTargetColor', 'fColorMix', 'fPickingColor' ],
};
}

Expand Down Expand Up @@ -156,4 +196,11 @@ export class StraightPath extends Edges<CurvedPathEdgeData, GLCurvedPathEdgeType

return edgesMappings;
}

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);
}
}
}
18 changes: 16 additions & 2 deletions src/graph/edges/path/StraightPath.vs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,39 @@ layout(location=2) in uint iPointB;
layout(location=3) in uint iColorA;
layout(location=4) in uint iColorB;
layout(location=5) in vec2 iColorMix;
layout(location=6) in uvec4 iPickingColor;

uniform bool uPicking;

uniform mat4 uViewMatrix;
uniform mat4 uSceneMatrix;
uniform mat4 uProjectionMatrix;
uniform vec2 uViewportSize;
uniform float uPixelRatio;
uniform float uPickingWidth;
uniform sampler2D uGraphPoints;
uniform sampler2D uColorPalette;

uniform float uLineWidth;

flat out float fLineWidth;
flat out vec4 fPickingColor;
out vec3 vColor;
out vec2 vProjectedPosition;
out float vProjectedW;

#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() {
fPickingColor = uPicking ? vec4(iPickingColor) / 255.0 : vec4(0.0);

float multA = aVertex.y;
float multB = 1.0 - aVertex.y;

Expand All @@ -42,7 +56,7 @@ void main() {
vec2 direction = normalize(bScreen - aScreen);
vec2 perp = vec2(-direction.y, direction.x);

fLineWidth = uLineWidth * uPixelRatio;
fLineWidth = (uPicking ? uLineWidth * uPickingWidth : uLineWidth) * uPixelRatio;
float offsetWidth = fLineWidth + 0.5;
vec4 position = aProjected * multA + bProjected * multB;
vec4 offset = vec4(((aVertex.x * perp * offsetWidth) / uViewportSize) * position.w, 0.0, 0.0);
Expand Down

0 comments on commit 0811545

Please sign in to comment.