commit f1ee73fbc8f8759f124e7dd47dcab53387942dcb Author: Connor Johnstone Date: Wed Oct 14 14:50:57 2026 -0400 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..91a92af --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,14 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "resolved" +version = "0.1.0" + +[[package]] +name = "resolved-cli" +version = "0.1.0" +dependencies = [ + "resolved", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..2795dbe --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,15 @@ +[workspace] +members = ["crates/resolved", "crates/resolved-cli"] +resolver = "2" + +[workspace.package] +version = "0.1.0" +edition = "2021" +# The oldest toolchain this is tested against, not the oldest it might compile on. +rust-version = "1.89" +authors = ["Connor Johnstone"] +license = "MIT" +repository = "https://git.rcjohnstone.com/connor/resolved" + +[workspace.dependencies] +resolved = { path = "crates/resolved" } diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f91cac7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Connor Johnstone + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/crates/resolved-cli/Cargo.toml b/crates/resolved-cli/Cargo.toml new file mode 100644 index 0000000..1530dde --- /dev/null +++ b/crates/resolved-cli/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "resolved-cli" +description = "Command-line front end for the resolved renderer" +publish = false +version.workspace = true +edition.workspace = true +rust-version.workspace = true +authors.workspace = true +license.workspace = true +repository.workspace = true + +[[bin]] +name = "resolved" +path = "src/main.rs" + +[dependencies] +resolved.workspace = true diff --git a/crates/resolved-cli/src/main.rs b/crates/resolved-cli/src/main.rs new file mode 100644 index 0000000..69ed1ec --- /dev/null +++ b/crates/resolved-cli/src/main.rs @@ -0,0 +1,5 @@ +//! The `resolved` command. Rendering arrives with the `render` subcommand. + +fn main() { + println!("resolved {}", env!("CARGO_PKG_VERSION")); +} diff --git a/crates/resolved/Cargo.toml b/crates/resolved/Cargo.toml new file mode 100644 index 0000000..f3e740b --- /dev/null +++ b/crates/resolved/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "resolved" +description = "Radiometric rendering of resolved spacecraft imagery" +readme = "readme.md" +keywords = ["spacecraft", "rendering", "camera", "radiometry", "spaceflight"] +categories = ["science", "aerospace", "rendering"] +version.workspace = true +edition.workspace = true +rust-version.workspace = true +authors.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] diff --git a/crates/resolved/readme.md b/crates/resolved/readme.md new file mode 120000 index 0000000..2e75a7b --- /dev/null +++ b/crates/resolved/readme.md @@ -0,0 +1 @@ +../../readme.md \ No newline at end of file diff --git a/crates/resolved/src/lib.rs b/crates/resolved/src/lib.rs new file mode 100644 index 0000000..e6fb4a6 --- /dev/null +++ b/crates/resolved/src/lib.rs @@ -0,0 +1,10 @@ +//! Radiometric rendering of resolved spacecraft imagery. +//! +//! # Conventions +//! +//! - Everything is SI: meters, seconds, radians, watts. +//! - Scene state is f64 in an inertial frame; only camera-relative f32 reaches the GPU. + +// The readme is the crate's front page, so its examples cannot drift from the API. +#![doc = include_str!("../readme.md")] +#![warn(missing_docs)] diff --git a/hooks/pre-commit b/hooks/pre-commit new file mode 100755 index 0000000..bd782e6 --- /dev/null +++ b/hooks/pre-commit @@ -0,0 +1,43 @@ +#!/bin/sh +# Enable with: git config core.hooksPath hooks +# Skip a single commit with: git commit --no-verify + +set -e + +echo "pre-commit: cargo fmt --check" +cargo fmt --check + +echo "pre-commit: cargo clippy" +cargo clippy --workspace --all-targets --all-features -- -D warnings + +echo "pre-commit: cargo test --lib" +cargo test --workspace --lib --quiet + +echo "pre-commit: US spelling" +staged=$(git diff --cached --name-only --diff-filter=ACM -- '*.rs' '*.md' '*.toml' '*.wgsl') +if [ -n "$staged" ]; then + # shellcheck disable=SC2086 + hits=$(git grep -wniE -e 'metre|metres|kilometre|kilometres' \ + -e 'licence|defence|programme|catalogue|grey' \ + -e 'manoeuvre|manoeuvres|manoeuvred|manoeuvring' \ + -e 'normalise|normalised|normalises|normalising|normalisation' \ + -e 'stabilise|stabilised|stabilises|stabilising|stabilisation' \ + -e 'recognise|recognised|recognises|recognising' \ + -e 'serialise|serialised|serialises|serialising|serialisation' \ + -e 'behaviour|behaviours|colour|colours|centre|centres' \ + -e 'analyse|analysed|analyses|analysing' \ + -e 'organise|organised|organisation|optimise|optimised|optimisation' \ + -e 'initialise|initialised|initialisation|utilise|utilised' \ + -e 'rasterise|rasterised|rasterising|rasterisation' \ + -e 'modelling|modelled|labelled|cancelled|travelled' \ + -e 'favour|favours|honour|honours|neighbour|neighbours' \ + --cached -- $staged || true) + if [ -n "$hits" ]; then + echo "$hits" + echo + echo "pre-commit: British spellings found above. This project uses US English." + exit 1 + fi +fi + +echo "pre-commit: ok" diff --git a/hooks/pre-push b/hooks/pre-push new file mode 100755 index 0000000..54fca37 --- /dev/null +++ b/hooks/pre-push @@ -0,0 +1,16 @@ +#!/bin/sh +# Enable with: git config core.hooksPath hooks +# The slow checks: doctests link a binary each, and the doc build. + +set -e + +echo "pre-push: cargo test" +cargo test --workspace --all-features --quiet + +echo "pre-push: cargo test --no-default-features" +cargo test --workspace --no-default-features --quiet + +echo "pre-push: cargo doc" +RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --all-features --quiet + +echo "pre-push: ok" diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..1678f86 --- /dev/null +++ b/readme.md @@ -0,0 +1,59 @@ +# resolved + +Renders what a spacecraft camera sees: Earth, Moon, Sun and a target +spacecraft loaded from a mesh. The inputs are an epoch, the observer and target +states and attitudes, and a camera model. Images are radiometric: the renderer +works in radiance and converts to electrons and then DN through the camera's +optics and detector, so an image should match what a real camera with the same +parameters records. + +It is built for closed-loop simulation, where each step renders one frame and +latency is the number that matters. The target is 1–2 MP RGB in under 100 ms +end to end on a mid-range GPU (the reference is an RTX 3060). Lighting fidelity +and camera fidelity are selected separately, and each tier is benchmarked, so +a run can trade fidelity for speed knowing what each step costs. + +Rendering goes through wgpu. On a machine without a GPU, the same shaders run +on the CPU through Mesa's lavapipe (`vulkan-swrast` on Arch, +`mesa-vulkan-drivers` on Debian and Ubuntu). + +## Status + +Early development. Nothing renders yet. The work is tracked as Gitea +milestones, each split into one issue per change: + +| Milestone | Scope | +|---|---| +| M1 | Scene API, headless wgpu, analytic Earth/Moon/Sun, glTF and STL targets, Lambert shading with eclipse, pinhole camera, radiance to DN, CLI, benchmark baseline | +| M2 | Self-shadowing, Earthshine and Moonshine, Earth and Moon albedo maps, Sun limb darkening | +| M3 | Lens distortion, PSF, detector noise, saturation and blooming, stars | +| M4 | BRDF and spectral materials, atmospheric scattering, clouds, lunar terrain | +| M5 | Portable ray tracing, path tracing, label outputs for ML | +| M6 | Validation against lunar, Earth and Mitsuba references; motion blur, rolling shutter, stray light; multi-band and 4k | + +## Conventions + +- SI units throughout: meters, seconds, radians, watts. +- Scene state is f64 in an inertial frame (GCRF). The GPU only sees f32 + coordinates relative to the camera. + +## Layout + +- `crates/resolved`: the library. +- `crates/resolved-cli`: the `resolved` command, for rendering without writing + a host program. + +## Development + +Point git at the committed hooks once per clone: + +```sh +git config core.hooksPath hooks +``` + +`pre-commit` runs formatting, clippy and the library unit tests; `pre-push` +runs the full test suite, including doctests, and the documentation build. + +## License + +MIT