Octahedron normals
- Dominant language
- Rust
- Stars
- 118
- Forks
- 8
- PR merge metrics
- No merged PRs in 30d
Description
Hey there!
Have you considered encoding normals using octahedron mapping? It's a neat way to map a direction vector into two components and it has a more uniform distribution than storing `(angle, z)`.
I haven't profiled it against the current implementation, but here's some sample code:
code
```rs
use glam::{Vec2, Vec3};
/// Encode a 3d direction vector to a 2d vector using octahedron mapping.
/// The output vector is in the range [-1..1]. The input vector doesn't have to be normalized.
pub fn encode_oct(dir: Vec3) -> Vec2 {
let norm = dir.x.abs() + dir.y.abs() + dir.z.abs();
let nx = dir.x / norm;
let ny = dir.y / norm;
if dir.z.is_sign_positive() {
Vec2::new(nx, ny)
} else {
// fold over negative z
Vec2::new(
(1.0 - ny.abs()) * nx.signum(),
(1.0 - nx.abs()) * ny.signum(),
)
}
}
/// Decode an octahedron mapped direction vector back to the original one.
/// The output is normalized.
pub fn decode_oct(mut oct: Vec2) -> Vec3 {
let z = 1.0 - oct.x.abs() - oct.y.abs();
oct += oct.signum() * z.min(0.0);
Vec3::new(oct.x, oct.y, z).normalize()
}
```
If you want to, I could open a PR to compare it to the current impl.
Contributor guide
Research direction
Start by locating the current normal encoding implementation and compare it with the supplied Rust octahedron encode/decode sample. Profile both approaches and document whether the octahedron mapping improves distribution or file size without harming the format's goals.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- computer-graphics
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100