radial sugiyama positioning integration

This commit is contained in:
Oxy8
2026-03-23 11:13:27 -03:00
parent 6b9115e43b
commit 696844f341
51 changed files with 10089 additions and 364 deletions

View File

@@ -76,6 +76,9 @@ export class Renderer {
private selectedProgram: WebGLProgram;
private neighborProgram: WebGLProgram;
private vao: WebGLVertexArrayObject;
private nodeVbo: WebGLBuffer;
private lineVao: WebGLVertexArrayObject;
private lineVbo: WebGLBuffer;
// Data
private leaves: Leaf[] = [];
@@ -88,6 +91,8 @@ export class Renderer {
private leafEdgeStarts: Uint32Array = new Uint32Array(0);
private leafEdgeCounts: Uint32Array = new Uint32Array(0);
private maxPtSize = 256;
private useRawLineSegments = false;
private rawLineVertexCount = 0;
// Multi-draw extension
private multiDrawExt: any = null;
@@ -163,15 +168,23 @@ export class Renderer {
// Create VAO + VBO (empty for now)
this.vao = gl.createVertexArray()!;
this.nodeVbo = gl.createBuffer()!;
gl.bindVertexArray(this.vao);
const vbo = gl.createBuffer()!;
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bindBuffer(gl.ARRAY_BUFFER, this.nodeVbo);
// We forced a_pos to location 0 in compileProgram
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
gl.bindVertexArray(null);
this.lineVao = gl.createVertexArray()!;
this.lineVbo = gl.createBuffer()!;
gl.bindVertexArray(this.lineVao);
gl.bindBuffer(gl.ARRAY_BUFFER, this.lineVbo);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
gl.bindVertexArray(null);
this.linesIbo = gl.createBuffer()!;
this.selectionIbo = gl.createBuffer()!;
this.neighborIbo = gl.createBuffer()!;
@@ -192,7 +205,8 @@ export class Renderer {
xs: Float32Array,
ys: Float32Array,
vertexIds: Uint32Array,
edges: Uint32Array
edges: Uint32Array,
routeLineVertices: Float32Array | null = null
): number {
const t0 = performance.now();
const gl = this.gl;
@@ -213,6 +227,7 @@ export class Renderer {
// Upload sorted particles to GPU as STATIC VBO (never changes)
gl.bindVertexArray(this.vao);
gl.bindBuffer(gl.ARRAY_BUFFER, this.nodeVbo);
gl.bufferData(gl.ARRAY_BUFFER, sorted, gl.STATIC_DRAW);
gl.bindVertexArray(null);
@@ -236,6 +251,19 @@ export class Renderer {
}
this.vertexIdToSortedIndex = vertexIdToSortedIndex;
this.useRawLineSegments = routeLineVertices !== null && routeLineVertices.length > 0;
this.rawLineVertexCount = this.useRawLineSegments && routeLineVertices ? routeLineVertices.length / 2 : 0;
if (this.useRawLineSegments && routeLineVertices) {
this.edgeCount = edgeCount;
this.leafEdgeStarts = new Uint32Array(0);
this.leafEdgeCounts = new Uint32Array(0);
gl.bindVertexArray(this.lineVao);
gl.bindBuffer(gl.ARRAY_BUFFER, this.lineVbo);
gl.bufferData(gl.ARRAY_BUFFER, routeLineVertices, gl.STATIC_DRAW);
gl.bindVertexArray(null);
return performance.now() - t0;
}
// Remap edges from vertex IDs to sorted indices
const lineIndices = new Uint32Array(edgeCount * 2);
let validEdges = 0;
@@ -572,24 +600,30 @@ export class Renderer {
}
// 5. Draw Lines if deeply zoomed in (< 20k total visible particles)
if (totalVisibleParticles < 20000 && visibleCount > 0) {
if (totalVisibleParticles < 20000) {
gl.useProgram(this.lineProgram);
gl.uniform2f(this.uCenterLine, this.cx, this.cy);
gl.uniform2f(this.uScaleLine, (this.zoom * 2) / cw, (-this.zoom * 2) / ch);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.linesIbo);
if (this.useRawLineSegments) {
gl.bindVertexArray(this.lineVao);
gl.drawArrays(gl.LINES, 0, this.rawLineVertexCount);
gl.bindVertexArray(this.vao);
} else if (visibleCount > 0) {
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.linesIbo);
for (let i = 0; i < visibleCount; i++) {
const leafIdx = this.visibleLeafIndices[i];
const edgeCount = this.leafEdgeCounts[leafIdx];
if (edgeCount === 0) continue;
// Each edge is 2 indices (1 line segment)
// Offset is in bytes: edgeStart * 2 (indices per edge) * 4 (bytes per uint32)
const edgeStart = this.leafEdgeStarts[leafIdx];
gl.drawElements(gl.LINES, edgeCount * 2, gl.UNSIGNED_INT, edgeStart * 2 * 4);
for (let i = 0; i < visibleCount; i++) {
const leafIdx = this.visibleLeafIndices[i];
const edgeCount = this.leafEdgeCounts[leafIdx];
if (edgeCount === 0) continue;
// Each edge is 2 indices (1 line segment)
// Offset is in bytes: edgeStart * 2 (indices per edge) * 4 (bytes per uint32)
const edgeStart = this.leafEdgeStarts[leafIdx];
gl.drawElements(gl.LINES, edgeCount * 2, gl.UNSIGNED_INT, edgeStart * 2 * 4);
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}
// 6. Draw Neighbor Nodes (yellow) - drawn before selected so selected appears on top