Skip to content

Conversation

@MasahiroOgawa
Copy link

@MasahiroOgawa MasahiroOgawa commented Dec 26, 2025

Objective

Add measuring 2 point distance function. And also add rescale, save new ply function.

Test result

I added these functions to example as below.
image

This is the new function test movie.
Screencast from 2025-12-25 17-05-38.webm

Summary

This PR adds a new feature for measuring distances between two points on a Gaussian splat model and rescaling the model based on a known distance.

New Features

  • Distance Measurement: Click two points on a 3DGS model to measure the distance between them
  • Model Rescaling: Enter a known real-world distance and rescale the entire model
  • PLY Export: Export the rescaled model as a standard PLY file
  • Interactive Point Adjustment: Drag points along ray lines to fine-tune positions

New Files

  • src/PlyWriter.ts - PLY export library for PackedSplats data
  • examples/distance-rescale/ - Interactive example demonstrating the feature
  • test/PlyWriter.test.ts - Unit tests for PlyWriter (15 test cases)

Key Implementation Details

  • Ray-based point selection with nearest Gaussian intersection
  • Constant screen-size markers (always visible regardless of zoom)
  • Billboard ring outlines for marker visibility against any background
  • Proper Three.js resource disposal to prevent memory leaks

Tests Added

  • 15 unit tests for PlyWriter covering:
    • Constructor with default/custom options
    • PLY header generation validation
    • Binary data size verification
    • Position, scale, quaternion encoding
    • Log scale encoding with zero fallback
    • Sigmoid opacity encoding with edge case clamping
    • Color DC coefficient encoding
    • Empty splats handling
    • Big endian format support
    • Multiple splats ordering

Bug Fixes

  • Fixed format string in PlyWriter: replace()replaceAll() for proper "binary little endian" output

🤖 Generated with Claude Code

MasahiroOgawa and others added 10 commits December 25, 2025 13:42
- Add PlyWriter class to export PackedSplats to standard PLY format
- Add distance-rescale example with interactive point selection
- Support ray-based point selection with visible ray lines
- Allow dragging points along ray lines to adjust depth
- Implement model rescaling based on measured vs desired distance
- Export rescaled models as PLY files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add PlyWriter class to export PackedSplats to standard PLY format
- Add distance-rescale example with interactive point selection
- Support ray-based point selection with visible ray lines
- Allow dragging points along ray lines to adjust depth
- Implement model rescaling based on measured vs desired distance
- Export rescaled models as PLY files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Switch from SparkControls to OrbitControls for reliability
- Auto-center camera on model using getBoundingBox
- Dynamic marker/ray sizing based on model dimensions
- Change newDistance to text input (was slider limited to 0.001-100)
- Add proper rotation.x = Math.PI for PLY orientation
- Improve error handling and add debug logging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Increase marker radius from 0.5% to 2% of model size
- Add white ring outline around markers for contrast
- Ring billboards to always face camera
- Markers now visible against any background

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove overly restrictive minT clamping (was markerRadius*5, now 0.01)
- Allow movement beyond visible ray line (maxT = rayLineLength * 2)
- Keep current point when rays are parallel instead of jumping
- Pass current point to closestPointOnRay for better fallback behavior

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The markers are now THREE.Group (sphere + ring), so intersectObjects
returns child meshes, not the group. Walk up the parent chain to find
which marker group was actually hit.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove world-space marker sizing (markerRadius)
- Add MARKER_SCREEN_SIZE constant (3% of screen height)
- Scale markers dynamically based on camera distance in render loop
- Markers now stay same visual size when zooming in/out

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add explicit else-if check for point2 in drag handler for safety
- Add disposeObject helper to properly dispose Three.js geometries/materials
- Prevent memory leaks when resetting selection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 15 comprehensive unit tests for PlyWriter:
  - Constructor with default/custom options
  - PLY header generation validation
  - Binary data size verification
  - Position, scale, quaternion encoding
  - Log scale encoding with zero fallback
  - Sigmoid opacity encoding with edge case clamping
  - Color DC coefficient encoding
  - Empty splats handling
  - Big endian format support
  - Multiple splats ordering

- Fix bug: replace() only replaced first underscore in format string
  Changed to replaceAll() for proper "binary little endian" output

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PLY reader expects "binary_little_endian" with underscores, not spaces.
This was causing exported PLY files to fail to load (appearing all black).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@dmarcos
Copy link
Contributor

dmarcos commented Dec 29, 2025

Thanks. I'm not sure if this should be a core spark feature or leave it as a 3rd party library / component. It seems too specific

@MasahiroOgawa
Copy link
Author

Thank you for your response. I think this feature will be the reason to select spark as a default Gaussian splatting viewer, because there is no viewer in the world which can measure and rescale the model. Currently only reall3D viewer has a distance measurement function, but it can only select 2 points in 2D space, cannot rescale nor save,and it is totally in Chinese. So if this is approved, spark is the only one Gaussian splatting viewer in the world, which can measure and insert a real scale into the created Gaussian spot model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants