Skip to main content

loam_render/raymarch/scene/
primitive4.rs

1use glam::Vec4;
2use loam_shape::Shape;
3
4use super::literal::wgsl_f32;
5use super::SENTINEL_DISTANCE;
6
7pub trait Primitive4 {
8    fn to_wgsl_4d(&self, name: &str) -> String;
9
10    fn eval_4d(&self, p: Vec4) -> f32;
11}
12
13impl Primitive4 for Shape {
14    fn to_wgsl_4d(&self, name: &str) -> String {
15        match self {
16            Shape::HyperSphere4D { center, radius } => format!(
17                "fn {name}(p: vec4<f32>) -> f32 {{\n\
18                \treturn length(p - vec4<f32>({cx}, {cy}, {cz}, {cw})) - ({radius});\n\
19                }}\n",
20                name = name,
21                cx = wgsl_f32(center.x),
22                cy = wgsl_f32(center.y),
23                cz = wgsl_f32(center.z),
24                cw = wgsl_f32(center.w),
25                radius = wgsl_f32(*radius),
26            ),
27
28            Shape::ConvexPolytope4D { .. } => format!(
29                "fn {name}(_p: vec4<f32>) -> f32 {{\n\
30                \t// ConvexPolytope4D: half-space emit lives in the\n\
31                \t// render node's per-frame uniform path, not here.\n\
32                \t// See Hyperslice4DNode.\n\
33                \treturn {SENTINEL_DISTANCE:e};\n\
34                }}\n",
35            ),
36
37            Shape::HalfSpace4D { normal, offset } => format!(
38                "fn {name}(p: vec4<f32>) -> f32 {{\n\
39                \treturn dot(p, vec4<f32>({nx}, {ny}, {nz}, {nw})) - ({offset});\n\
40                }}\n",
41                name = name,
42                nx = wgsl_f32(normal.x),
43                ny = wgsl_f32(normal.y),
44                nz = wgsl_f32(normal.z),
45                nw = wgsl_f32(normal.w),
46                offset = wgsl_f32(*offset),
47            ),
48
49            Shape::Sphere { .. }
50            | Shape::HalfSpace { .. }
51            | Shape::Box3 { .. }
52            | Shape::Polygon2D { .. }
53            | Shape::ConvexPolytope3D { .. } => format!(
54                "fn {name}(_p: vec4<f32>) -> f32 {{\n\
55                \treturn {SENTINEL_DISTANCE:e};\n\
56                }}\n",
57            ),
58        }
59    }
60
61    fn eval_4d(&self, p: Vec4) -> f32 {
62        match self {
63            Shape::HyperSphere4D { center, radius } => (p - *center).length() - *radius,
64
65            Shape::ConvexPolytope4D { .. } => SENTINEL_DISTANCE,
66
67            Shape::HalfSpace4D { normal, offset } => p.dot(*normal) - *offset,
68
69            Shape::Sphere { .. }
70            | Shape::HalfSpace { .. }
71            | Shape::Box3 { .. }
72            | Shape::Polygon2D { .. }
73            | Shape::ConvexPolytope3D { .. } => SENTINEL_DISTANCE,
74        }
75    }
76}