simview 6.2.0__tar.gz → 6.2.1__tar.gz

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 (108) hide show
  1. {simview-6.2.0/simview.egg-info → simview-6.2.1}/PKG-INFO +1 -1
  2. {simview-6.2.0 → simview-6.2.1}/pyproject.toml +1 -1
  3. {simview-6.2.0 → simview-6.2.1}/simview/static/js/objects/Terrain.js +142 -56
  4. {simview-6.2.0 → simview-6.2.1}/simview/static/js/objects/colormap.js +19 -0
  5. {simview-6.2.0 → simview-6.2.1/simview.egg-info}/PKG-INFO +1 -1
  6. {simview-6.2.0 → simview-6.2.1}/LICENSE +0 -0
  7. {simview-6.2.0 → simview-6.2.1}/MANIFEST.in +0 -0
  8. {simview-6.2.0 → simview-6.2.1}/README.md +0 -0
  9. {simview-6.2.0 → simview-6.2.1}/setup.cfg +0 -0
  10. {simview-6.2.0 → simview-6.2.1}/simview/__init__.py +0 -0
  11. {simview-6.2.0 → simview-6.2.1}/simview/__main__.py +0 -0
  12. {simview-6.2.0 → simview-6.2.1}/simview/columnar.py +0 -0
  13. {simview-6.2.0 → simview-6.2.1}/simview/diff.py +0 -0
  14. {simview-6.2.0 → simview-6.2.1}/simview/info.py +0 -0
  15. {simview-6.2.0 → simview-6.2.1}/simview/launcher.py +0 -0
  16. {simview-6.2.0 → simview-6.2.1}/simview/live.py +0 -0
  17. {simview-6.2.0 → simview-6.2.1}/simview/merge.py +0 -0
  18. {simview-6.2.0 → simview-6.2.1}/simview/model.py +0 -0
  19. {simview-6.2.0 → simview-6.2.1}/simview/py.typed +0 -0
  20. {simview-6.2.0 → simview-6.2.1}/simview/remote.py +0 -0
  21. {simview-6.2.0 → simview-6.2.1}/simview/render.py +0 -0
  22. {simview-6.2.0 → simview-6.2.1}/simview/scene.py +0 -0
  23. {simview-6.2.0 → simview-6.2.1}/simview/server.py +0 -0
  24. {simview-6.2.0 → simview-6.2.1}/simview/state.py +0 -0
  25. {simview-6.2.0 → simview-6.2.1}/simview/static/css/controls.css +0 -0
  26. {simview-6.2.0 → simview-6.2.1}/simview/static/js/SimView.js +0 -0
  27. {simview-6.2.0 → simview-6.2.1}/simview/static/js/components/AnimationController.js +0 -0
  28. {simview-6.2.0 → simview-6.2.1}/simview/static/js/components/BatchManager.js +0 -0
  29. {simview-6.2.0 → simview-6.2.1}/simview/static/js/components/InteractionController.js +0 -0
  30. {simview-6.2.0 → simview-6.2.1}/simview/static/js/components/Scene.js +0 -0
  31. {simview-6.2.0 → simview-6.2.1}/simview/static/js/components/StateStore.js +0 -0
  32. {simview-6.2.0 → simview-6.2.1}/simview/static/js/components/WindowedField.js +0 -0
  33. {simview-6.2.0 → simview-6.2.1}/simview/static/js/config.js +0 -0
  34. {simview-6.2.0 → simview-6.2.1}/simview/static/js/main.js +0 -0
  35. {simview-6.2.0 → simview-6.2.1}/simview/static/js/objects/Body.js +0 -0
  36. {simview-6.2.0 → simview-6.2.1}/simview/static/js/objects/Polyline.js +0 -0
  37. {simview-6.2.0 → simview-6.2.1}/simview/static/js/objects/StaticObject.js +0 -0
  38. {simview-6.2.0 → simview-6.2.1}/simview/static/js/objects/similarity.js +0 -0
  39. {simview-6.2.0 → simview-6.2.1}/simview/static/js/objects/utils.js +0 -0
  40. {simview-6.2.0 → simview-6.2.1}/simview/static/js/ui/AnalysisPanel.js +0 -0
  41. {simview-6.2.0 → simview-6.2.1}/simview/static/js/ui/BatchLegend.js +0 -0
  42. {simview-6.2.0 → simview-6.2.1}/simview/static/js/ui/BodyStateWindow.js +0 -0
  43. {simview-6.2.0 → simview-6.2.1}/simview/static/js/ui/Controls.js +0 -0
  44. {simview-6.2.0 → simview-6.2.1}/simview/static/js/ui/ErrorMetrics.js +0 -0
  45. {simview-6.2.0 → simview-6.2.1}/simview/static/js/ui/Legend.js +0 -0
  46. {simview-6.2.0 → simview-6.2.1}/simview/static/js/ui/PlaybackControls.js +0 -0
  47. {simview-6.2.0 → simview-6.2.1}/simview/static/js/ui/ScalarPlotter.js +0 -0
  48. {simview-6.2.0 → simview-6.2.1}/simview/static/js/ui/TerrainProfile.js +0 -0
  49. {simview-6.2.0 → simview-6.2.1}/simview/static/js/ui/chartControls.js +0 -0
  50. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/batchPresets.js +0 -0
  51. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/batchVisibility.js +0 -0
  52. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/blobCodec.js +0 -0
  53. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/blobWindow.js +0 -0
  54. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/bodyTransforms.js +0 -0
  55. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/cameraRange.js +0 -0
  56. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/csv.js +0 -0
  57. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/episodes.js +0 -0
  58. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/errorMath.js +0 -0
  59. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/interpolate.js +0 -0
  60. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/keyboard.js +0 -0
  61. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/liveFollow.js +0 -0
  62. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/scalarSeries.js +0 -0
  63. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/terrainSample.js +0 -0
  64. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/uplot.js +0 -0
  65. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/viewState.js +0 -0
  66. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/viewerDefaults.js +0 -0
  67. {simview-6.2.0 → simview-6.2.1}/simview/static/js/utils/visibleRanges.js +0 -0
  68. {simview-6.2.0 → simview-6.2.1}/simview/static/lib/js-colormaps.js +0 -0
  69. {simview-6.2.0 → simview-6.2.1}/simview/static/lib/three-0.174.0/addons/controls/OrbitControls.js +0 -0
  70. {simview-6.2.0 → simview-6.2.1}/simview/static/lib/three-0.174.0/addons/libs/lil-gui.module.min.js +0 -0
  71. {simview-6.2.0 → simview-6.2.1}/simview/static/lib/three-0.174.0/three.core.js +0 -0
  72. {simview-6.2.0 → simview-6.2.1}/simview/static/lib/three-0.174.0/three.module.js +0 -0
  73. {simview-6.2.0 → simview-6.2.1}/simview/static/lib/uPlot.esm.js +0 -0
  74. {simview-6.2.0 → simview-6.2.1}/simview/static/lib/uPlot.min.css +0 -0
  75. {simview-6.2.0 → simview-6.2.1}/simview/static/textures/contacts/red-cross0.png +0 -0
  76. {simview-6.2.0 → simview-6.2.1}/simview/static/textures/points/ball1.png +0 -0
  77. {simview-6.2.0 → simview-6.2.1}/simview/templates/index.html +0 -0
  78. {simview-6.2.0 → simview-6.2.1}/simview/terrain.py +0 -0
  79. {simview-6.2.0 → simview-6.2.1}/simview/utils.py +0 -0
  80. {simview-6.2.0 → simview-6.2.1}/simview/view.py +0 -0
  81. {simview-6.2.0 → simview-6.2.1}/simview.egg-info/SOURCES.txt +0 -0
  82. {simview-6.2.0 → simview-6.2.1}/simview.egg-info/dependency_links.txt +0 -0
  83. {simview-6.2.0 → simview-6.2.1}/simview.egg-info/entry_points.txt +0 -0
  84. {simview-6.2.0 → simview-6.2.1}/simview.egg-info/requires.txt +0 -0
  85. {simview-6.2.0 → simview-6.2.1}/simview.egg-info/top_level.txt +0 -0
  86. {simview-6.2.0 → simview-6.2.1}/tests/test_batch_selection.py +0 -0
  87. {simview-6.2.0 → simview-6.2.1}/tests/test_cli.py +0 -0
  88. {simview-6.2.0 → simview-6.2.1}/tests/test_columnar_ondisk.py +0 -0
  89. {simview-6.2.0 → simview-6.2.1}/tests/test_columnar_states.py +0 -0
  90. {simview-6.2.0 → simview-6.2.1}/tests/test_contacts.py +0 -0
  91. {simview-6.2.0 → simview-6.2.1}/tests/test_diff.py +0 -0
  92. {simview-6.2.0 → simview-6.2.1}/tests/test_embed_defaults.py +0 -0
  93. {simview-6.2.0 → simview-6.2.1}/tests/test_episodes.py +0 -0
  94. {simview-6.2.0 → simview-6.2.1}/tests/test_info.py +0 -0
  95. {simview-6.2.0 → simview-6.2.1}/tests/test_launcher.py +0 -0
  96. {simview-6.2.0 → simview-6.2.1}/tests/test_live.py +0 -0
  97. {simview-6.2.0 → simview-6.2.1}/tests/test_merge.py +0 -0
  98. {simview-6.2.0 → simview-6.2.1}/tests/test_pointcloud_features.py +0 -0
  99. {simview-6.2.0 → simview-6.2.1}/tests/test_remote.py +0 -0
  100. {simview-6.2.0 → simview-6.2.1}/tests/test_roundtrip.py +0 -0
  101. {simview-6.2.0 → simview-6.2.1}/tests/test_scene.py +0 -0
  102. {simview-6.2.0 → simview-6.2.1}/tests/test_server.py +0 -0
  103. {simview-6.2.0 → simview-6.2.1}/tests/test_show.py +0 -0
  104. {simview-6.2.0 → simview-6.2.1}/tests/test_terrain.py +0 -0
  105. {simview-6.2.0 → simview-6.2.1}/tests/test_terrain_query.py +0 -0
  106. {simview-6.2.0 → simview-6.2.1}/tests/test_trajectory.py +0 -0
  107. {simview-6.2.0 → simview-6.2.1}/tests/test_utils.py +0 -0
  108. {simview-6.2.0 → simview-6.2.1}/tests/test_view.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simview
3
- Version: 6.2.0
3
+ Version: 6.2.1
4
4
  Summary: THREE.js-based simulation visualization tool
5
5
  Author-email: Jan Vlk <vlkjan6@fel.cvut.cz>, Ales Kucera <kuceral4@fel.cvut.cz>, David Korcak <david.korcak@gmail.com>
6
6
  License-Expression: BSD-3-Clause
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "simview"
7
- version = "6.2.0"
7
+ version = "6.2.1"
8
8
  readme = "README.md"
9
9
  requires-python = ">=3.12"
10
10
  license = "BSD-3-Clause"
@@ -1,6 +1,6 @@
1
1
  import * as THREE from "three";
2
2
  import { TERRAIN_CONFIG, THEME } from "../config.js";
3
- import { getCallableFromColorMapName } from "./colormap.js";
3
+ import { colormapLUT, getCallableFromColorMapName } from "./colormap.js";
4
4
  import { toFlatFloat32Array } from "./utils.js";
5
5
 
6
6
  export class Terrain {
@@ -177,10 +177,12 @@ export class Terrain {
177
177
  shininess: 10,
178
178
  });
179
179
 
180
- const wireframeMaterial = new THREE.MeshBasicMaterial({
180
+ // Each grid edge is drawn once (see #createWireframeGeometry), where
181
+ // a `wireframe: true` mesh drew every interior edge twice at 0.2;
182
+ // 0.36 = 1 - (1 - 0.2)^2 keeps the same look.
183
+ const wireframeMaterial = new THREE.LineBasicMaterial({
181
184
  color: 0xffffff,
182
- wireframe: true,
183
- opacity: 0.2,
185
+ opacity: 0.36,
184
186
  transparent: true,
185
187
  });
186
188
 
@@ -194,6 +196,7 @@ export class Terrain {
194
196
  const { surfaceMaterial, wireframeMaterial } = this.#createMaterials();
195
197
 
196
198
  let singletonSurfaceGeometry = null;
199
+ let singletonWireframeGeometry = null;
197
200
  let singletonNormals = null;
198
201
 
199
202
  if (this.isSingleton) {
@@ -202,6 +205,7 @@ export class Terrain {
202
205
  0,
203
206
  normals?.[0]
204
207
  );
208
+ singletonWireframeGeometry = this.#createWireframeGeometry(singletonSurfaceGeometry);
205
209
  singletonNormals = this.#createNormalVectors(
206
210
  heightData[0],
207
211
  normals?.[0]
@@ -224,8 +228,16 @@ export class Terrain {
224
228
  surfaceMesh.castShadow = true;
225
229
  batchGroup.add(surfaceMesh);
226
230
 
227
- const wireframeMesh = new THREE.Mesh(surfaceGeometry, wireframeMaterial);
231
+ const wireframeMesh = new THREE.LineSegments(
232
+ this.isSingleton
233
+ ? singletonWireframeGeometry
234
+ : this.#createWireframeGeometry(surfaceGeometry),
235
+ wireframeMaterial
236
+ );
228
237
  wireframeMesh.name = "wireframe";
238
+ // The probe only uses "surface" hits; raycasting millions of
239
+ // segments here just cost every click ~0.5 s.
240
+ wireframeMesh.raycast = () => {};
229
241
  batchGroup.add(wireframeMesh);
230
242
 
231
243
  const surfaceNormals = this.isSingleton
@@ -308,64 +320,127 @@ export class Terrain {
308
320
  #createSurfaceGeometryFromHeightData(heightData, batchIndex, normals) {
309
321
  const { sizeX, sizeY, resolutionX, resolutionY } = this.dimensions;
310
322
  const { minX, minY, maxX, maxY } = this.bounds;
311
- // Create a plane geometry with the right number of segments
312
- const geometry = new THREE.PlaneGeometry(
313
- sizeX,
314
- sizeY,
315
- resolutionX - 1,
316
- resolutionY - 1
317
- );
318
- // Center the geometry based on bounds
319
- const centerX = (minX + maxX) / 2;
320
- const centerY = (minY + maxY) / 2;
321
- geometry.translate(centerX, centerY, 0);
322
- // Get attributes for direct manipulation
323
- const position = geometry.attributes.position;
324
- // Create color buffer
325
- const colorAttribute = new THREE.BufferAttribute(
326
- new Float32Array(position.count * 3),
327
- 3
328
- );
329
- geometry.setAttribute("color", colorAttribute);
323
+ const count = resolutionX * resolutionY;
324
+ // Same vertices and triangles as THREE.PlaneGeometry(sizeX, sizeY,
325
+ // resolutionX - 1, resolutionY - 1) centred on the bounds -- rows run
326
+ // top (max Y) to bottom, so vertex row r is data row resolutionY - r - 1
327
+ // -- but written straight into typed arrays: PlaneGeometry's JS-array
328
+ // build is ~10x slower on a 1.6M-vertex heightfield.
329
+ const left = (minX + maxX) / 2 - sizeX / 2;
330
+ const top = (minY + maxY) / 2 + sizeY / 2;
331
+ const stepX = sizeX / (resolutionX - 1);
332
+ const stepY = sizeY / (resolutionY - 1);
333
+
334
+ // Supplied normals aren't guaranteed unit length (scene.py writes
335
+ // (-dz/dx, -dz/dy, 1) as-is); without any, they're computed below so
336
+ // slopes still get a shading cue.
337
+ const flatNormals = ArrayBuffer.isView(normals);
338
+ const normalCount = flatNormals ? normals.length / 3 : normals?.length ?? 0;
339
+ const useSuppliedNormals = normalCount === count;
340
+
341
+ const positions = new Float32Array(count * 3);
342
+ const normalArray = useSuppliedNormals ? new Float32Array(count * 3) : null;
343
+ for (let r = 0, i = 0; r < resolutionY; r++) {
344
+ const y = top - r * stepY;
345
+ const rowStart = (resolutionY - r - 1) * resolutionX;
346
+ for (let col = 0; col < resolutionX; col++, i += 3) {
347
+ const dataIndex = rowStart + col;
348
+ positions[i] = left + col * stepX;
349
+ positions[i + 1] = y;
350
+ positions[i + 2] = heightData[dataIndex];
351
+ if (!normalArray) continue;
352
+ let nx, ny, nz;
353
+ if (flatNormals) {
354
+ const base = dataIndex * 3;
355
+ nx = normals[base];
356
+ ny = normals[base + 1];
357
+ nz = normals[base + 2];
358
+ } else {
359
+ [nx, ny, nz] = normals[dataIndex];
360
+ }
361
+ const inv = 1 / (Math.sqrt(nx * nx + ny * ny + nz * nz) || 1);
362
+ nx *= inv;
363
+ ny *= inv;
364
+ nz *= inv;
365
+ if (!Number.isFinite(nx + ny + nz)) {
366
+ nx = 0;
367
+ ny = 0;
368
+ nz = 1;
369
+ }
370
+ normalArray[i] = nx;
371
+ normalArray[i + 1] = ny;
372
+ normalArray[i + 2] = nz;
373
+ }
374
+ }
330
375
 
331
- // Apply height data to geometry
332
- // NOTE: THREE.js PlaneGeometry vertices are arranged in rows from bottom to top (Y increases)
333
- const callableColormap = getCallableFromColorMapName(
334
- this.app.uiState.terrainColorMap
376
+ const indices = new (count > 65535 ? Uint32Array : Uint16Array)(
377
+ (resolutionX - 1) * (resolutionY - 1) * 6
335
378
  );
336
-
337
- // PlaneGeometry ships flat (0, 0, 1) normals, so without this the
338
- // surface is lit as if it were level and slopes get no shading cue.
339
- const normalCount = ArrayBuffer.isView(normals) ? normals.length / 3 : normals?.length ?? 0;
340
- const useSuppliedNormals = normalCount === position.count;
341
- const normal = geometry.attributes.normal;
342
- const n = new THREE.Vector3();
343
-
344
- for (let i = 0; i < position.count; i++) {
345
- // Convert vertex index to grid coordinates
346
- const col = i % resolutionX;
347
- const invertedRow = Math.floor(i / resolutionX);
348
- const row = resolutionY - invertedRow - 1; // Invert row index
349
- // Calculate index in the flattened height data array
350
- const dataIndex = row * resolutionX + col;
351
- // Set Z coordinate (height)
352
- position.setZ(i, heightData[dataIndex]);
353
- if (useSuppliedNormals) {
354
- // Supplied normals aren't guaranteed unit length (scene.py
355
- // writes (-dz/dx, -dz/dy, 1) as-is).
356
- n.fromArray(Terrain.#normalAt(normals, dataIndex)).normalize();
357
- if (!Number.isFinite(n.x + n.y + n.z)) n.set(0, 0, 1);
358
- normal.setXYZ(i, n.x, n.y, n.z);
379
+ for (let r = 0, k = 0; r < resolutionY - 1; r++) {
380
+ for (let col = 0; col < resolutionX - 1; col++) {
381
+ const a = r * resolutionX + col;
382
+ const b = a + resolutionX;
383
+ indices[k++] = a;
384
+ indices[k++] = b;
385
+ indices[k++] = a + 1;
386
+ indices[k++] = b;
387
+ indices[k++] = b + 1;
388
+ indices[k++] = a + 1;
359
389
  }
360
390
  }
361
- if (useSuppliedNormals) normal.needsUpdate = true;
391
+
392
+ const geometry = new THREE.BufferGeometry();
393
+ geometry.setIndex(new THREE.BufferAttribute(indices, 1));
394
+ geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
395
+ geometry.setAttribute("color", new THREE.BufferAttribute(new Float32Array(count * 3), 3));
396
+ if (normalArray) geometry.setAttribute("normal", new THREE.BufferAttribute(normalArray, 3));
362
397
  else geometry.computeVertexNormals();
363
398
 
399
+ const callableColormap = getCallableFromColorMapName(
400
+ this.app.uiState.terrainColorMap
401
+ );
402
+
364
403
  // Apply colors
365
404
  this.#updateSurfaceColor(batchIndex, geometry, callableColormap);
405
+ return geometry;
406
+ }
366
407
 
367
- // Make sure changes are applied
368
- position.needsUpdate = true;
408
+ // The surface's triangle edges as line segments, each edge once:
409
+ // horizontal, vertical, and the diagonal the two triangles of a cell
410
+ // share. Shares the surface's position buffer, so only the index is new --
411
+ // three's `wireframe: true` instead builds a JS array of every triangle's
412
+ // three edges (interior ones twice), ~10x slower on a 1.6M-vertex grid.
413
+ #createWireframeGeometry(surfaceGeometry) {
414
+ const { resolutionX, resolutionY } = this.dimensions;
415
+ const count = resolutionX * resolutionY;
416
+ const indices = new (count > 65535 ? Uint32Array : Uint16Array)(
417
+ 2 *
418
+ ((resolutionX - 1) * resolutionY +
419
+ resolutionX * (resolutionY - 1) +
420
+ (resolutionX - 1) * (resolutionY - 1))
421
+ );
422
+ for (let r = 0, k = 0; r < resolutionY; r++) {
423
+ for (let col = 0; col < resolutionX; col++) {
424
+ const a = r * resolutionX + col;
425
+ const right = col < resolutionX - 1;
426
+ const down = r < resolutionY - 1;
427
+ if (right) {
428
+ indices[k++] = a;
429
+ indices[k++] = a + 1;
430
+ }
431
+ if (down) {
432
+ indices[k++] = a;
433
+ indices[k++] = a + resolutionX;
434
+ }
435
+ if (right && down) {
436
+ indices[k++] = a + 1;
437
+ indices[k++] = a + resolutionX;
438
+ }
439
+ }
440
+ }
441
+ const geometry = new THREE.BufferGeometry();
442
+ geometry.setAttribute("position", surfaceGeometry.attributes.position);
443
+ geometry.setIndex(new THREE.BufferAttribute(indices, 1));
369
444
  return geometry;
370
445
  }
371
446
 
@@ -508,6 +583,9 @@ export class Terrain {
508
583
  }
509
584
 
510
585
  // Update all colors based on the new colormap
586
+ const lut = colormapLUT(callableColormap);
587
+ const lutLast = lut.length / 3 - 1;
588
+ const colors = colorAttribute.array;
511
589
  for (let i = 0; i < position.count; i++) {
512
590
  let value;
513
591
  if (mode === "diff") {
@@ -567,8 +645,16 @@ export class Terrain {
567
645
  value = this.calculateNormalizedHeight(position.getZ(i));
568
646
  }
569
647
  }
570
- const color = callableColormap(value);
571
- colorAttribute.setXYZ(i, color.r, color.g, color.b);
648
+ if (Number.isFinite(value)) {
649
+ const k = Math.round(Math.max(0, Math.min(1, value)) * lutLast) * 3;
650
+ colors[i * 3] = lut[k];
651
+ colors[i * 3 + 1] = lut[k + 1];
652
+ colors[i * 3 + 2] = lut[k + 2];
653
+ } else {
654
+ // No data: the callable's neutral grey, not a colormap end.
655
+ const color = callableColormap(value);
656
+ colorAttribute.setXYZ(i, color.r, color.g, color.b);
657
+ }
572
658
  }
573
659
  // Update the buffer
574
660
  colorAttribute.needsUpdate = true;
@@ -44,3 +44,22 @@ export function getCallableFromColorMapName(cmapName) {
44
44
  );
45
45
  return (value) => new THREE.Color(value, 0.2, 1 - value);
46
46
  }
47
+
48
+ /**
49
+ * Samples a colormap callable at `size` evenly spaced values over [0, 1] into
50
+ * a flat RGB table, so colouring a million-vertex terrain is an array lookup
51
+ * per vertex instead of a colormap evaluation plus a THREE.Color allocation.
52
+ * @param {(value: number) => THREE.Color} callable
53
+ * @param {number} [size]
54
+ * @returns {Float32Array} size * 3 floats, r/g/b of sample k at k * 3
55
+ */
56
+ export function colormapLUT(callable, size = 1024) {
57
+ const lut = new Float32Array(size * 3);
58
+ for (let k = 0; k < size; k++) {
59
+ const c = callable(k / (size - 1));
60
+ lut[k * 3] = c.r;
61
+ lut[k * 3 + 1] = c.g;
62
+ lut[k * 3 + 2] = c.b;
63
+ }
64
+ return lut;
65
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simview
3
- Version: 6.2.0
3
+ Version: 6.2.1
4
4
  Summary: THREE.js-based simulation visualization tool
5
5
  Author-email: Jan Vlk <vlkjan6@fel.cvut.cz>, Ales Kucera <kuceral4@fel.cvut.cz>, David Korcak <david.korcak@gmail.com>
6
6
  License-Expression: BSD-3-Clause
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes