Skip to content

Latest commit

 

History

History
216 lines (158 loc) · 7.42 KB

CLAUDE.md

File metadata and controls

216 lines (158 loc) · 7.42 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

A web-based triangle mesh viewer with progressive LOD (Level of Detail) using Potree's octree streaming infrastructure. Converts OFF mesh files to a custom format combining centroids (for Potree octree indexing) with full triangle geometry (for rendering), enabling efficient viewing of large meshes (~1M+ triangles) in the browser.

Architecture

Data Pipeline (Python)

OFF → PLY+BIN → LAS → Potree Octree

  1. off2centroids.py: Parse OFF mesh file, compute triangle centroids with colors and original_index, output:

    • centroids.ply: Centroid points (x, y, z, r, g, b, original_index)
    • potree/triangles.bin: Binary file with 9 floats per triangle (v0.xyz, v1.xyz, v2.xyz)
  2. convert.py: Orchestrates full pipeline:

    • OFF → PLY+BIN (via off2centroids.py)
    • PLY → LAS (via pdal translate with extra_dims)
    • LAS → Potree octree (via PotreeConverter)

Key Insight: Centroids are indexed by Potree's octree for LOD, while full triangle geometry lives in a separate binary file indexed by original_index.

Viewer (JavaScript/Three.js)

Three.js + potree-core + Custom Triangle LOD Manager

Located in viewer/:

  • src/main.js: Scene setup, camera, TrackballControls, main render loop
  • src/TriangleLODManager.js: Syncs triangle meshes with Potree's visible nodes
    • Watches potree-core's LOD node visibility
    • Loads potree/triangles.bin via HTTP Range requests (progressive loading)
    • Creates/destroys Three.js meshes based on visible nodes
    • Maps Potree node points → original_index → triangle geometry
  • src/TrackballHelper.js: Camera control utilities (WASD movement, mouse orbit)

Key Insight: TriangleLODManager uses HTTP Range requests to fetch only the triangles needed for currently visible Potree nodes, avoiding loading the entire file upfront.

Common Commands

Python (Backend)

# Convert OFF mesh to Potree format
uv run python convert.py input.off output_dir/

# Run individual tests
uv run python off2centroids_test.py
uv run python ply2las_test.py
uv run python potree_convert_test.py

Viewer (Frontend)

cd viewer/

# Development server (Vite)
bun dev

# Build for production
bun build

# Lint
bun lint

# Format code
bun format
bun format:check

Viewing Results

# Serve from repo root
python3 -m http.server 8080

# Open in browser (old standalone HTML)
http://localhost:8080/triangle_splatting.html?data=output_dir

# Open in browser (new Vite viewer)
cd viewer && bun dev
# Then open http://localhost:5173/?data=../output_garden

External Dependencies

Data Format Details

centroids.ply

  • Standard PLY point cloud with custom property original_index (uint32)
  • Preserved through LAS conversion via ply2las.py (pure Python, laspy)
  • Indexed by Potree's octree for spatial LOD queries

Potree Output (self-contained, distributable)

potree/
├── metadata.json      # Octree bounds, scale, point count + SH config
├── hierarchy.bin      # Node hierarchy (which nodes exist)
├── octree.bin         # Point data (centroids with original_index)
├── triangles.bin      # Triangle vertex offsets (9 float32 × 36 bytes each)
└── sh0.bin, sh1.bin...# SH coefficients per degree (optional)

triangles.bin

  • Lives inside potree/ alongside the octree data
  • Binary format: [triangle0, triangle1, ...]
  • Each triangle: 9 consecutive float32 values (x1,y1,z1, x2,y2,z2, x3,y3,z3)
  • Size: 36 bytes per triangle (9 floats × 4 bytes)
  • Accessed via HTTP Range requests: byte_offset = original_index * 36

Code Quality Principles

Core Principles

  1. KISS - Prefer simple solutions (e.g., static binary file over complex database)
  2. DRY - Search codebase for existing patterns before creating new ones
  3. YAGNI - Build only what's needed now (no premature abstractions)
  4. Leverage Libraries - Use maintained libraries. Don't reinvent wheels. In this repo, for example, use Three.js, potree-core, PDAL instead of reimplementing.
  5. No Magic - Explicit configuration (hardcoded paths in convert.py are acceptable for local tools)
  6. Clear Separation of Concerns - One purpose per file/class. Models ≠ logic. Data pipeline (Python) ≠ Viewer (JS)
  7. Dependency Injection - Pass dependencies in (config, clients), don't import globally.
  8. Small, Focused Interfaces - Minimal abstract base classes. Easy to extend.
  9. Named Objects Over Tuples - For 3+ return values, use Pydantic models with named fields instead of positional tuples.

Code Reuse and Planning (CRITICAL)

BEFORE writing ANY new code:

  1. Search the codebase thoroughly - Use Grep/Glob to find similar functionality
  2. Reuse existing patterns - Follow established patterns (collectors, models, adapters)
  3. Check for library solutions - Can libraries solve this? (maybe search in internet if unsure and needed)
  4. Spend time planning - In plan mode, invest CONSIDERABLE time creating detailed plans

Planning checklist (MANDATORY):

  • Identified exact problem (WHERE code is, WHAT issue is, WHY it matters, HOW to fix)
  • Searched codebase for existing solutions to reuse
  • Verified no library can solve this
  • Questioned every abstraction (YAGNI - do we really need it?)
  • Planned specific steps (exact files, line numbers, actions)
  • Identified risks and mitigations
  • Kept it simple (KISS - simplest approach that works)

Git Practices

  • Use git add <specific-file> not git add -A
  • Review diffs before committing
  • No git commit --amend unless explicitly asked
  • CRITICAL: Do NOT reference Claude in commit messages or code

Common Mistakes to Avoid (CRITICAL)

NEVER do these things - they violate our core principles:

File Management

  • DON'T create new files unless absolutely necessary -> Edit existing files
  • DON'T proactively create documentation files (.md, README) -> Only when explicitly requested
  • DON'T add emojis to code or documentation -> Only use when explicitly requested

Git Practices

  • DON'T use git add -A or git add . -> Use git add <specific-file>
  • DON'T commit without reviewing changes -> Always review diffs first
  • DON'T skip writing tests for new functionality -> Write tests for changes
  • DON'T use git commit --amend unless explicitly asked -> Create new commits

Code Quality

  • DON'T reinvent existing functionality -> Search codebase and reuse patterns
  • DON'T add unnecessary abstractions -> Build only what's needed now (YAGNI)
  • DON'T return 3+ values in unnamed tuples -> Use Pydantic models with named fields
  • DON'T mix models with business logic -> Separate concerns clearly
  • DON'T import globally -> Use dependency injection
  • DON'T add "magic" behavior (guessing, parsing, fallbacks) -> Explicit configuration only

Development Process

  • DON'T skip planning phase -> Use plan mode and complete planning checklist
  • DON'T ignore existing libraries -> Use LiteLLM, Pydantic, instructor, etc.
  • DON'T do more than asked -> Do what's asked, nothing more, nothing less