@chartts/gl 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/bar3d.cjs +4 -4
  2. package/dist/bar3d.d.cts +2 -2
  3. package/dist/bar3d.d.ts +2 -2
  4. package/dist/bar3d.js +1 -1
  5. package/dist/{chunk-XGQDO4VO.js → chunk-AGG2KSBO.js} +265 -41
  6. package/dist/chunk-AGG2KSBO.js.map +1 -0
  7. package/dist/{chunk-JCECG2KY.cjs → chunk-OTQKQDB6.cjs} +266 -40
  8. package/dist/chunk-OTQKQDB6.cjs.map +1 -0
  9. package/dist/{factory-Cp9Kr7aa.d.cts → factory-jQSzXhK4.d.cts} +4 -1
  10. package/dist/{factory-Cp9Kr7aa.d.ts → factory-jQSzXhK4.d.ts} +4 -1
  11. package/dist/flow-gl.cjs +4 -4
  12. package/dist/flow-gl.d.cts +2 -2
  13. package/dist/flow-gl.d.ts +2 -2
  14. package/dist/flow-gl.js +1 -1
  15. package/dist/globe3d.cjs +4 -4
  16. package/dist/globe3d.d.cts +2 -2
  17. package/dist/globe3d.d.ts +2 -2
  18. package/dist/globe3d.js +1 -1
  19. package/dist/graph-gl.cjs +4 -4
  20. package/dist/graph-gl.d.cts +2 -2
  21. package/dist/graph-gl.d.ts +2 -2
  22. package/dist/graph-gl.js +1 -1
  23. package/dist/index.cjs +60 -52
  24. package/dist/index.d.cts +3 -2
  25. package/dist/index.d.ts +3 -2
  26. package/dist/index.js +1 -1
  27. package/dist/line3d.cjs +4 -4
  28. package/dist/line3d.d.cts +2 -2
  29. package/dist/line3d.d.ts +2 -2
  30. package/dist/line3d.js +1 -1
  31. package/dist/lines-gl.cjs +4 -4
  32. package/dist/lines-gl.d.cts +2 -2
  33. package/dist/lines-gl.d.ts +2 -2
  34. package/dist/lines-gl.js +1 -1
  35. package/dist/lines3d.cjs +4 -4
  36. package/dist/lines3d.d.cts +2 -2
  37. package/dist/lines3d.d.ts +2 -2
  38. package/dist/lines3d.js +1 -1
  39. package/dist/map3d.cjs +4 -4
  40. package/dist/map3d.d.cts +2 -2
  41. package/dist/map3d.d.ts +2 -2
  42. package/dist/map3d.js +1 -1
  43. package/dist/scatter-gl.cjs +4 -4
  44. package/dist/scatter-gl.d.cts +2 -2
  45. package/dist/scatter-gl.d.ts +2 -2
  46. package/dist/scatter-gl.js +1 -1
  47. package/dist/scatter3d.cjs +4 -4
  48. package/dist/scatter3d.d.cts +2 -2
  49. package/dist/scatter3d.d.ts +2 -2
  50. package/dist/scatter3d.js +1 -1
  51. package/dist/surface3d.cjs +4 -4
  52. package/dist/surface3d.d.cts +2 -2
  53. package/dist/surface3d.d.ts +2 -2
  54. package/dist/surface3d.js +1 -1
  55. package/dist/torus3d-NpDo5Nb5.d.ts +15 -0
  56. package/dist/torus3d-fgZpxxQZ.d.cts +15 -0
  57. package/dist/torus3d.cjs +20 -0
  58. package/dist/torus3d.cjs.map +1 -0
  59. package/dist/torus3d.d.cts +2 -0
  60. package/dist/torus3d.d.ts +2 -0
  61. package/dist/torus3d.js +3 -0
  62. package/dist/torus3d.js.map +1 -0
  63. package/package.json +7 -2
  64. package/dist/chunk-JCECG2KY.cjs.map +0 -1
  65. package/dist/chunk-XGQDO4VO.js.map +0 -1
package/dist/bar3d.cjs CHANGED
@@ -1,20 +1,20 @@
1
1
  'use strict';
2
2
 
3
- var chunkJCECG2KY_cjs = require('./chunk-JCECG2KY.cjs');
3
+ var chunkOTQKQDB6_cjs = require('./chunk-OTQKQDB6.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "Bar3D", {
8
8
  enumerable: true,
9
- get: function () { return chunkJCECG2KY_cjs.Bar3D; }
9
+ get: function () { return chunkOTQKQDB6_cjs.Bar3D; }
10
10
  });
11
11
  Object.defineProperty(exports, "createBar3DPlugin", {
12
12
  enumerable: true,
13
- get: function () { return chunkJCECG2KY_cjs.createBar3DPlugin; }
13
+ get: function () { return chunkOTQKQDB6_cjs.createBar3DPlugin; }
14
14
  });
15
15
  Object.defineProperty(exports, "createGLChart", {
16
16
  enumerable: true,
17
- get: function () { return chunkJCECG2KY_cjs.createGLChart; }
17
+ get: function () { return chunkOTQKQDB6_cjs.createGLChart; }
18
18
  });
19
19
  //# sourceMappingURL=bar3d.cjs.map
20
20
  //# sourceMappingURL=bar3d.cjs.map
package/dist/bar3d.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { e as GLChartTypePlugin } from './factory-Cp9Kr7aa.cjs';
2
- export { B as Bar3D, b as GLChartData, c as GLChartInstance, d as GLChartOptions, f as GLDataPoint, x as createGLChart } from './factory-Cp9Kr7aa.cjs';
1
+ import { e as GLChartTypePlugin } from './factory-jQSzXhK4.cjs';
2
+ export { B as Bar3D, b as GLChartData, c as GLChartInstance, d as GLChartOptions, f as GLDataPoint, x as createGLChart } from './factory-jQSzXhK4.cjs';
3
3
 
4
4
  /**
5
5
  * Bar3D — cuboid mesh per bar, Phong lit.
package/dist/bar3d.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { e as GLChartTypePlugin } from './factory-Cp9Kr7aa.js';
2
- export { B as Bar3D, b as GLChartData, c as GLChartInstance, d as GLChartOptions, f as GLDataPoint, x as createGLChart } from './factory-Cp9Kr7aa.js';
1
+ import { e as GLChartTypePlugin } from './factory-jQSzXhK4.js';
2
+ export { B as Bar3D, b as GLChartData, c as GLChartInstance, d as GLChartOptions, f as GLDataPoint, x as createGLChart } from './factory-jQSzXhK4.js';
3
3
 
4
4
  /**
5
5
  * Bar3D — cuboid mesh per bar, Phong lit.
package/dist/bar3d.js CHANGED
@@ -1,3 +1,3 @@
1
- export { Bar3D, createBar3DPlugin, createGLChart } from './chunk-XGQDO4VO.js';
1
+ export { Bar3D, createBar3DPlugin, createGLChart } from './chunk-AGG2KSBO.js';
2
2
  //# sourceMappingURL=bar3d.js.map
3
3
  //# sourceMappingURL=bar3d.js.map
@@ -1838,6 +1838,7 @@ function createGlobe3DPlugin() {
1838
1838
  let sphereIBO = null;
1839
1839
  let sphereIndexCount = 0;
1840
1840
  const modelMatrix = mat4();
1841
+ let locationColors = /* @__PURE__ */ new Map();
1841
1842
  const normalMatrix = new Float32Array(9);
1842
1843
  let screenPoints = [];
1843
1844
  let seriesInfo = [];
@@ -1854,34 +1855,49 @@ function createGlobe3DPlugin() {
1854
1855
  [...MESH_VERT_UNIFORMS, ...MESH_FRAG_UNIFORMS],
1855
1856
  MESH_VERT_ATTRIBUTES
1856
1857
  );
1857
- const patches = [];
1858
- let maxVal = 0;
1859
- for (const s of series) for (const v of s.values) if (Math.abs(v) > maxVal) maxVal = Math.abs(v);
1860
- if (maxVal === 0) maxVal = 1;
1858
+ const locationMap = /* @__PURE__ */ new Map();
1861
1859
  seriesInfo = [];
1862
1860
  screenPoints = [];
1863
1861
  for (let sIdx = 0; sIdx < series.length; sIdx++) {
1864
1862
  const s = series[sIdx];
1865
1863
  const colorHex = s.color ?? theme.colors[sIdx % theme.colors.length];
1866
- const color = hexToRGB(colorHex);
1867
1864
  seriesInfo.push({ name: s.name, color: colorHex });
1868
1865
  for (let di = 0; di < s.values.length; di++) {
1869
1866
  const lat = s.y?.[di] ?? 0, lng = s.x?.[di] ?? 0, value = s.values[di];
1870
- const normValue = Math.abs(value) / maxVal;
1871
- patches.push({ lat, lng, value, normValue, color, si: sIdx, di, name: s.name, label: data.categories?.[di] ?? "" });
1867
+ const label = data.categories?.[di] ?? "";
1868
+ const key = `${lat.toFixed(1)}_${lng.toFixed(1)}`;
1869
+ let loc = locationMap.get(key);
1870
+ if (!loc) {
1871
+ loc = { lat, lng, totalValue: 0, label, entries: [] };
1872
+ locationMap.set(key, loc);
1873
+ }
1874
+ loc.totalValue += Math.abs(value);
1875
+ loc.entries.push({ si: sIdx, di, value });
1872
1876
  const [wx, wy, wz] = latLngToXYZ(lat, lng, GLOBE_RADIUS);
1873
- screenPoints.push({ si: sIdx, di, lat, lng, wx, wy, wz, value, name: s.name, label: data.categories?.[di] ?? "" });
1877
+ screenPoints.push({ si: sIdx, di, lat, lng, wx, wy, wz, value, name: s.name, label });
1874
1878
  }
1875
1879
  }
1880
+ const patches = [];
1881
+ locationColors = /* @__PURE__ */ new Map();
1882
+ let maxVal = 0;
1883
+ for (const loc of locationMap.values()) if (loc.totalValue > maxVal) maxVal = loc.totalValue;
1884
+ if (maxVal === 0) maxVal = 1;
1885
+ let locIdx = 0;
1886
+ for (const loc of locationMap.values()) {
1887
+ const colorHex = theme.colors[locIdx % theme.colors.length];
1888
+ locationColors.set(loc.label, colorHex);
1889
+ const color = hexToRGB(colorHex);
1890
+ const normValue = loc.totalValue / maxVal;
1891
+ patches.push({ lat: loc.lat, lng: loc.lng, value: loc.totalValue, normValue, color, si: 0, di: locIdx, name: loc.label, label: loc.label });
1892
+ locIdx++;
1893
+ }
1876
1894
  const baseColor = [0.03, 0.05, 0.12];
1877
1895
  const patchRadius = 0.8;
1878
1896
  const gratLatStep = 30, gratLngStep = 30;
1879
1897
  const gratWidth = 0.015;
1880
1898
  const gratColor = [0.08, 0.12, 0.22];
1881
- console.log(`[Globe3D] Building sphere ${SEGMENTS}x${RINGS}, ${patches.length} data patches`);
1882
1899
  const verts = [];
1883
1900
  const indices = [];
1884
- let patchedVerts = 0;
1885
1901
  for (let ring = 0; ring <= RINGS; ring++) {
1886
1902
  const phi = ring / RINGS * Math.PI;
1887
1903
  const lat = 90 - ring / RINGS * 180;
@@ -1915,7 +1931,6 @@ function createGlobe3DPlugin() {
1915
1931
  }
1916
1932
  }
1917
1933
  if (ar > 0.01 || ag > 0.01 || ab > 0.01) {
1918
- patchedVerts++;
1919
1934
  r = Math.min(1, r + ar);
1920
1935
  g = Math.min(1, g + ag);
1921
1936
  b = Math.min(1, b + ab);
@@ -1933,12 +1948,11 @@ function createGlobe3DPlugin() {
1933
1948
  );
1934
1949
  }
1935
1950
  }
1936
- console.log(`[Globe3D] ${patchedVerts} / ${(RINGS + 1) * (SEGMENTS + 1)} vertices colored by data`);
1937
1951
  for (let ring = 0; ring < RINGS; ring++) {
1938
1952
  for (let seg = 0; seg < SEGMENTS; seg++) {
1939
1953
  const a = ring * (SEGMENTS + 1) + seg;
1940
1954
  const b = a + SEGMENTS + 1;
1941
- indices.push(a, b, a + 1, a + 1, b, b + 1);
1955
+ indices.push(a, a + 1, b, a + 1, b + 1, b);
1942
1956
  }
1943
1957
  }
1944
1958
  const vertArr = new Float32Array(verts);
@@ -1963,6 +1977,7 @@ function createGlobe3DPlugin() {
1963
1977
  setLightUniforms(prog, defaultLightConfig(), camera.position);
1964
1978
  prog.setFloat("u_opacity", progress);
1965
1979
  if (sphereVBO && sphereIBO) {
1980
+ gl.disable(gl.CULL_FACE);
1966
1981
  sphereVBO.bind();
1967
1982
  const layout = createVertexLayout([
1968
1983
  { location: prog.attributes["a_position"], size: 3 },
@@ -1974,6 +1989,7 @@ function createGlobe3DPlugin() {
1974
1989
  const indexType = gl.UNSIGNED_SHORT;
1975
1990
  gl.drawElements(gl.TRIANGLES, sphereIndexCount, indexType, 0);
1976
1991
  disableVertexLayout(gl, layout);
1992
+ gl.enable(gl.CULL_FACE);
1977
1993
  }
1978
1994
  },
1979
1995
  renderOverlay(ctx, ctx2d) {
@@ -1993,38 +2009,17 @@ function createGlobe3DPlugin() {
1993
2009
  );
1994
2010
  if (!screen || screen.z < -1 || screen.z > 1 || screen.z > 0.97) continue;
1995
2011
  seenLabels.add(sp.label);
1996
- ctx2d.fillStyle = theme.textColor;
1997
- ctx2d.globalAlpha = 0.7;
2012
+ const locColor = locationColors.get(sp.label) ?? theme.textColor;
2013
+ ctx2d.fillStyle = locColor;
2014
+ ctx2d.globalAlpha = 0.9;
1998
2015
  ctx2d.beginPath();
1999
- ctx2d.arc(screen.x, screen.y, 2.5, 0, Math.PI * 2);
2016
+ ctx2d.arc(screen.x, screen.y, 3, 0, Math.PI * 2);
2000
2017
  ctx2d.fill();
2001
2018
  ctx2d.fillStyle = theme.textColor;
2002
2019
  ctx2d.globalAlpha = 0.85;
2003
2020
  ctx2d.textAlign = "left";
2004
2021
  ctx2d.fillText(sp.label, screen.x + 8, screen.y);
2005
2022
  }
2006
- if (seriesInfo.length > 1) {
2007
- const lx = 12, ly = height - 14 - seriesInfo.length * 18;
2008
- ctx2d.fillStyle = "rgba(0,0,0,0.45)";
2009
- ctx2d.globalAlpha = 1;
2010
- ctx2d.beginPath();
2011
- ctx2d.roundRect(lx - 6, ly - 8, 120, seriesInfo.length * 18 + 12, 6);
2012
- ctx2d.fill();
2013
- ctx2d.textAlign = "left";
2014
- ctx2d.textBaseline = "top";
2015
- ctx2d.font = `${theme.fontSize - 1}px ${theme.fontFamily}`;
2016
- for (let i = 0; i < seriesInfo.length; i++) {
2017
- const s = seriesInfo[i];
2018
- const y = ly + i * 18;
2019
- ctx2d.fillStyle = s.color;
2020
- ctx2d.globalAlpha = 0.9;
2021
- ctx2d.beginPath();
2022
- ctx2d.arc(lx + 4, y + 6, 4, 0, Math.PI * 2);
2023
- ctx2d.fill();
2024
- ctx2d.fillStyle = "rgba(255,255,255,0.8)";
2025
- ctx2d.fillText(s.name, lx + 14, y);
2026
- }
2027
- }
2028
2023
  ctx2d.restore();
2029
2024
  },
2030
2025
  needsLoop() {
@@ -3493,6 +3488,230 @@ function createGraphGLPlugin() {
3493
3488
  };
3494
3489
  }
3495
3490
 
3491
+ // src/charts/torus3d/torus3d-type.ts
3492
+ var RADIAL_SEGMENTS = 64;
3493
+ var HEIGHT_STEPS = 200;
3494
+ var TOTAL_HEIGHT = 6;
3495
+ var MIN_RADIUS = 0.6;
3496
+ var MAX_RADIUS = 2;
3497
+ function createTorus3DPlugin() {
3498
+ let vbo = null;
3499
+ let ibo = null;
3500
+ let indexCount = 0;
3501
+ let use32bit = false;
3502
+ const modelMatrix = mat4();
3503
+ const normalMatrix = new Float32Array(9);
3504
+ let labelPoints = [];
3505
+ return {
3506
+ type: "torus3d",
3507
+ prepare(ctx) {
3508
+ const { renderer, data, options, theme } = ctx;
3509
+ const gl = renderer.gl;
3510
+ const series = data.series;
3511
+ renderer.registerProgram(
3512
+ "mesh",
3513
+ MESH_VERT,
3514
+ MESH_FRAG,
3515
+ [...MESH_VERT_UNIFORMS, ...MESH_FRAG_UNIFORMS],
3516
+ MESH_VERT_ATTRIBUTES
3517
+ );
3518
+ const s = series[0];
3519
+ if (!s || s.values.length === 0) return;
3520
+ const opts = options;
3521
+ const intensity = opts.intensity ?? 1;
3522
+ const numRings = s.values.length;
3523
+ let maxVal = 0;
3524
+ for (const v of s.values) if (Math.abs(v) > maxVal) maxVal = Math.abs(v);
3525
+ if (maxVal === 0) maxVal = 1;
3526
+ const ringRadii = [];
3527
+ for (let i = 0; i < numRings; i++) {
3528
+ const norm = Math.abs(s.values[i]) / maxVal;
3529
+ ringRadii.push((MIN_RADIUS + norm * (MAX_RADIUS - MIN_RADIUS)) * intensity);
3530
+ }
3531
+ const ringColors = [];
3532
+ const ringHexColors = [];
3533
+ for (let i = 0; i < numRings; i++) {
3534
+ const hex = theme.colors[i % theme.colors.length];
3535
+ ringHexColors.push(hex);
3536
+ ringColors.push(hexToRGB(hex));
3537
+ }
3538
+ function catmullRom(p0, p1, p2, p3, t) {
3539
+ return 0.5 * (2 * p1 + (-p0 + p2) * t + (2 * p0 - 5 * p1 + 4 * p2 - p3) * t * t + (-p0 + 3 * p1 - 3 * p2 + p3) * t * t * t);
3540
+ }
3541
+ function radiusAt(t) {
3542
+ const f = t * (numRings - 1);
3543
+ const i = Math.max(0, Math.min(Math.floor(f), numRings - 2));
3544
+ const frac = f - i;
3545
+ const p0 = ringRadii[Math.max(0, i - 1)];
3546
+ const p1 = ringRadii[i];
3547
+ const p2 = ringRadii[Math.min(numRings - 1, i + 1)];
3548
+ const p3 = ringRadii[Math.min(numRings - 1, i + 2)];
3549
+ return Math.max(MIN_RADIUS * 0.5, catmullRom(p0, p1, p2, p3, frac));
3550
+ }
3551
+ function colorAt(t) {
3552
+ const f = t * (numRings - 1);
3553
+ const i = Math.max(0, Math.min(Math.floor(f), numRings - 2));
3554
+ const frac = f - i;
3555
+ const c0 = ringColors[Math.max(0, i - 1)];
3556
+ const c1 = ringColors[i];
3557
+ const c2 = ringColors[Math.min(numRings - 1, i + 1)];
3558
+ const c3 = ringColors[Math.min(numRings - 1, i + 2)];
3559
+ return [
3560
+ Math.max(0, Math.min(1, catmullRom(c0[0], c1[0], c2[0], c3[0], frac))),
3561
+ Math.max(0, Math.min(1, catmullRom(c0[1], c1[1], c2[1], c3[1], frac))),
3562
+ Math.max(0, Math.min(1, catmullRom(c0[2], c1[2], c2[2], c3[2], frac)))
3563
+ ];
3564
+ }
3565
+ const verts = [];
3566
+ const indices = [];
3567
+ labelPoints = [];
3568
+ for (let h = 0; h <= HEIGHT_STEPS; h++) {
3569
+ const t = h / HEIGHT_STEPS;
3570
+ const y = (t - 0.5) * TOTAL_HEIGHT;
3571
+ const radius = radiusAt(t);
3572
+ const color = colorAt(t);
3573
+ const eps = 2e-3;
3574
+ const rPrev = radiusAt(Math.max(0, t - eps));
3575
+ const rNext = radiusAt(Math.min(1, t + eps));
3576
+ const drdy = (rNext - rPrev) / (2 * eps * TOTAL_HEIGHT);
3577
+ for (let seg = 0; seg <= RADIAL_SEGMENTS; seg++) {
3578
+ const theta = seg / RADIAL_SEGMENTS * Math.PI * 2;
3579
+ const cosT = Math.cos(theta);
3580
+ const sinT = Math.sin(theta);
3581
+ const nx = cosT;
3582
+ const ny = -drdy;
3583
+ const nz = sinT;
3584
+ const nlen = Math.sqrt(nx * nx + ny * ny + nz * nz) || 1;
3585
+ verts.push(
3586
+ radius * cosT,
3587
+ y,
3588
+ radius * sinT,
3589
+ nx / nlen,
3590
+ ny / nlen,
3591
+ nz / nlen,
3592
+ color[0],
3593
+ color[1],
3594
+ color[2]
3595
+ );
3596
+ }
3597
+ }
3598
+ for (let i = 0; i < numRings; i++) {
3599
+ const t = (i + 0.5) / numRings;
3600
+ const y = (t - 0.5) * TOTAL_HEIGHT;
3601
+ const r = ringRadii[i];
3602
+ labelPoints.push({
3603
+ si: 0,
3604
+ di: i,
3605
+ wx: r + 0.4,
3606
+ wy: y,
3607
+ wz: 0,
3608
+ value: s.values[i],
3609
+ label: data.categories?.[i] ?? `${i + 1}`,
3610
+ color: ringHexColors[i]
3611
+ });
3612
+ }
3613
+ for (let h = 0; h < HEIGHT_STEPS; h++) {
3614
+ for (let seg = 0; seg < RADIAL_SEGMENTS; seg++) {
3615
+ const a = h * (RADIAL_SEGMENTS + 1) + seg;
3616
+ const b = a + RADIAL_SEGMENTS + 1;
3617
+ indices.push(a, a + 1, b, a + 1, b + 1, b);
3618
+ }
3619
+ }
3620
+ const capStart = verts.length / 9;
3621
+ const bottomColor = colorAt(0);
3622
+ verts.push(0, -0.5 * TOTAL_HEIGHT, 0, 0, -1, 0, bottomColor[0], bottomColor[1], bottomColor[2]);
3623
+ const topColor = colorAt(1);
3624
+ verts.push(0, 0.5 * TOTAL_HEIGHT, 0, 0, 1, 0, topColor[0], topColor[1], topColor[2]);
3625
+ for (let seg = 0; seg < RADIAL_SEGMENTS; seg++) {
3626
+ indices.push(capStart, seg + 1, seg);
3627
+ const topRow = HEIGHT_STEPS * (RADIAL_SEGMENTS + 1);
3628
+ indices.push(capStart + 1, topRow + seg, topRow + seg + 1);
3629
+ }
3630
+ const vertArr = new Float32Array(verts);
3631
+ use32bit = verts.length / 9 > 65535;
3632
+ const idxArr = use32bit ? new Uint32Array(indices) : new Uint16Array(indices);
3633
+ if (vbo) vbo.update(vertArr);
3634
+ else vbo = createVertexBuffer(gl, vertArr, gl.DYNAMIC_DRAW);
3635
+ if (ibo) ibo.update(idxArr);
3636
+ else ibo = createIndexBuffer(gl, idxArr, gl.DYNAMIC_DRAW);
3637
+ indexCount = indices.length;
3638
+ mat4Identity(modelMatrix);
3639
+ },
3640
+ render(ctx) {
3641
+ const { renderer, camera } = ctx;
3642
+ const gl = renderer.gl;
3643
+ const prog = renderer.getProgram("mesh");
3644
+ prog.use();
3645
+ prog.setMat4("u_projView", camera.projViewMatrix);
3646
+ prog.setMat4("u_model", modelMatrix);
3647
+ mat3NormalFromMat4(normalMatrix, modelMatrix);
3648
+ prog.setMat3("u_normalMatrix", normalMatrix);
3649
+ setLightUniforms(prog, defaultLightConfig(), camera.position);
3650
+ prog.setFloat("u_opacity", ctx.animationProgress);
3651
+ if (vbo && ibo) {
3652
+ gl.disable(gl.CULL_FACE);
3653
+ vbo.bind();
3654
+ const layout = createVertexLayout([
3655
+ { location: prog.attributes["a_position"], size: 3 },
3656
+ { location: prog.attributes["a_normal"], size: 3 },
3657
+ { location: prog.attributes["a_color"], size: 3 }
3658
+ ]);
3659
+ applyVertexLayout(gl, layout);
3660
+ ibo.bind();
3661
+ gl.drawElements(gl.TRIANGLES, indexCount, use32bit ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT, 0);
3662
+ disableVertexLayout(gl, layout);
3663
+ gl.enable(gl.CULL_FACE);
3664
+ }
3665
+ },
3666
+ renderOverlay(ctx, ctx2d) {
3667
+ const { camera, width, height, theme, animationProgress } = ctx;
3668
+ if (animationProgress < 0.3) return;
3669
+ ctx2d.save();
3670
+ ctx2d.font = `bold ${theme.fontSize}px ${theme.fontFamily}`;
3671
+ ctx2d.textBaseline = "middle";
3672
+ for (const lp of labelPoints) {
3673
+ const screen = projectToScreen(new Float32Array([lp.wx, lp.wy, lp.wz]), camera.projViewMatrix, width, height);
3674
+ if (!screen || screen.z < -1 || screen.z > 1) continue;
3675
+ ctx2d.fillStyle = lp.color;
3676
+ ctx2d.globalAlpha = 0.9;
3677
+ ctx2d.beginPath();
3678
+ ctx2d.arc(screen.x, screen.y, 4, 0, Math.PI * 2);
3679
+ ctx2d.fill();
3680
+ ctx2d.fillStyle = theme.textColor;
3681
+ ctx2d.globalAlpha = 0.85;
3682
+ ctx2d.textAlign = "left";
3683
+ ctx2d.fillText(`${lp.label}: ${lp.value}`, screen.x + 10, screen.y);
3684
+ }
3685
+ ctx2d.restore();
3686
+ },
3687
+ needsLoop() {
3688
+ return false;
3689
+ },
3690
+ hitTest(ctx, x, y) {
3691
+ const { camera, width, height } = ctx;
3692
+ let closest = null;
3693
+ let closestDist = 30;
3694
+ for (const lp of labelPoints) {
3695
+ const screen = projectToScreen(new Float32Array([lp.wx, lp.wy, lp.wz]), camera.projViewMatrix, width, height);
3696
+ if (!screen || screen.z < -1 || screen.z > 1) continue;
3697
+ const dist = Math.sqrt((screen.x - x) ** 2 + (screen.y - y) ** 2);
3698
+ if (dist < closestDist) {
3699
+ closestDist = dist;
3700
+ closest = { seriesIndex: lp.si, dataIndex: lp.di, value: lp.value, x: screen.x, y: screen.y, seriesName: lp.label };
3701
+ }
3702
+ }
3703
+ return closest;
3704
+ },
3705
+ dispose() {
3706
+ vbo?.destroy();
3707
+ vbo = null;
3708
+ ibo?.destroy();
3709
+ ibo = null;
3710
+ labelPoints = [];
3711
+ }
3712
+ };
3713
+ }
3714
+
3496
3715
  // src/api/factory.ts
3497
3716
  function Scatter3D(container, opts) {
3498
3717
  const { data, ...options } = opts;
@@ -3569,7 +3788,12 @@ function GraphGL(container, opts) {
3569
3788
  const { data, ...options } = opts;
3570
3789
  return createGLChart(container, createGraphGLPlugin(), data, options);
3571
3790
  }
3791
+ function Torus3D(container, opts) {
3792
+ const { data, ...options } = opts;
3793
+ if (!options.camera) options.camera = { position: [4, 2, 6], target: [0, 0, 0] };
3794
+ return createGLChart(container, createTorus3DPlugin(), data, options);
3795
+ }
3572
3796
 
3573
- export { Bar3D, DEFAULT_GL_THEME, FlowGL, Globe3D, GraphGL, LIGHT_GL_THEME, Line3D, Lines3D, LinesGL, Map3D, Scatter3D, ScatterGL, Surface3D, applyVertexLayout, compileShader, createBar3DPlugin, createCamera, createFlowGLPlugin, createGLChart, createGLRenderer, createGlobe3DPlugin, createGraphGLPlugin, createGrid3D, createIndexBuffer, createLine3DPlugin, createLines3DPlugin, createLinesGLPlugin, createMap3DPlugin, createOrbitControls, createPickingSystem, createScatter3DPlugin, createScatterGLPlugin, createShaderProgram, createSurface3DPlugin, createVertexBuffer, createVertexLayout, defaultLightConfig, hexToRGB, mat4, mat4Identity, mat4Invert, mat4LookAt, mat4Multiply, mat4Perspective, projectToScreen, resolveTheme, setLightUniforms, toRad, updateCamera, updateOrbitControls, vec3 };
3574
- //# sourceMappingURL=chunk-XGQDO4VO.js.map
3575
- //# sourceMappingURL=chunk-XGQDO4VO.js.map
3797
+ export { Bar3D, DEFAULT_GL_THEME, FlowGL, Globe3D, GraphGL, LIGHT_GL_THEME, Line3D, Lines3D, LinesGL, Map3D, Scatter3D, ScatterGL, Surface3D, Torus3D, applyVertexLayout, compileShader, createBar3DPlugin, createCamera, createFlowGLPlugin, createGLChart, createGLRenderer, createGlobe3DPlugin, createGraphGLPlugin, createGrid3D, createIndexBuffer, createLine3DPlugin, createLines3DPlugin, createLinesGLPlugin, createMap3DPlugin, createOrbitControls, createPickingSystem, createScatter3DPlugin, createScatterGLPlugin, createShaderProgram, createSurface3DPlugin, createTorus3DPlugin, createVertexBuffer, createVertexLayout, defaultLightConfig, hexToRGB, mat4, mat4Identity, mat4Invert, mat4LookAt, mat4Multiply, mat4Perspective, projectToScreen, resolveTheme, setLightUniforms, toRad, updateCamera, updateOrbitControls, vec3 };
3798
+ //# sourceMappingURL=chunk-AGG2KSBO.js.map
3799
+ //# sourceMappingURL=chunk-AGG2KSBO.js.map