Environment Map Analysis: the model's faces as a mirror reflecting a studio (sky, horizon band, floor with light streaks, two light panels); toggles like the other surface analyses
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
4126ae5a75
commit
7a2b81fbf2
6 files changed
+39
-1
No files matched your search
@@ -19,6 +19,11 @@ pub static COMMANDS: &[CommandSpec] = &[
|
||||
.icon("draft_analysis")
|
||||
.noundo()
|
||||
.params("pull?: [x,y,z] direction (default Z); angle?: degrees (default 1); clear?: true turns the analysis off"),
|
||||
CommandSpec::new("FusionEnvironmentMapAnalysisCommand", "Environment Map Analysis", |s, p| set(s, p, SurfaceAnalysis::Environment))
|
||||
.at("SKETCH", "INSPECT")
|
||||
.icon("environment_map")
|
||||
.noundo()
|
||||
.params("clear?: true turns the analysis off"),
|
||||
CommandSpec::new("FusionCurvatureMapAnalysisCommand", "Curvature Map Analysis", curvature_map)
|
||||
.at("SKETCH", "INSPECT")
|
||||
.icon("curvature_map")
|
||||
@@ -88,6 +93,8 @@ mod tests {
|
||||
assert!(matches!(s.analysis, Some(SurfaceAnalysis::Draft { angle, .. }) if angle == 3.0));
|
||||
s.execute("FusionCurvatureMapAnalysisCommand", &json!({})).unwrap();
|
||||
assert!(matches!(s.analysis, Some(SurfaceAnalysis::Curvature { radius }) if (radius - 300f64.sqrt() / 10.0).abs() < 1e-6));
|
||||
s.execute("FusionEnvironmentMapAnalysisCommand", &json!({})).unwrap();
|
||||
assert_eq!(s.analysis, Some(SurfaceAnalysis::Environment));
|
||||
s.execute("FusionCurvatureMapAnalysisCommand", &json!({"clear": true})).unwrap();
|
||||
assert_eq!(s.analysis, None);
|
||||
assert_eq!(s.undo.len(), undo, "no undo steps");
|
||||
|
||||
@@ -176,6 +176,8 @@ pub enum SurfaceAnalysis {
|
||||
Draft { pull: Vec3, angle: f64 },
|
||||
/// Colour by curvature: blue flat, through green, to red at 1 / `radius`.
|
||||
Curvature { radius: f64 },
|
||||
/// Mirror finish reflecting a studio (sky, horizon, floor, light panels).
|
||||
Environment,
|
||||
}
|
||||
|
||||
const MAX_UNDO: usize = 200;
|
||||
|
||||
@@ -257,6 +257,21 @@ fn analysis(i: TOut) -> vec4<f32> {
|
||||
let c = select(0.08, 0.95, s > 0.0);
|
||||
return out_color(vec4<f32>(vec3<f32>(c), 1.0));
|
||||
}
|
||||
if (u.ana.x > 3.5) {
|
||||
// A studio around the model: sky above, a dark floor below, a bright horizon band and
|
||||
// two soft light panels, seen in a mirror.
|
||||
let r = reflect(-v, n);
|
||||
var c = mix(vec3<f32>(0.32, 0.34, 0.38), vec3<f32>(0.80, 0.86, 0.95), smoothstep(-0.05, 0.6, r.z));
|
||||
c = c + vec3<f32>(0.6) * exp(-abs(r.z) * 40.0);
|
||||
let side = atan2(r.y, r.x);
|
||||
c = c + vec3<f32>(0.9) * smoothstep(0.92, 0.98, cos(side * 2.0)) * smoothstep(0.1, 0.3, r.z) * smoothstep(0.8, 0.6, r.z);
|
||||
if (r.z < -0.02) {
|
||||
// The floor: lighter toward the horizon, with light-panel streaks along it.
|
||||
c = mix(vec3<f32>(0.55, 0.56, 0.60), vec3<f32>(0.20, 0.20, 0.22), clamp(-r.z * 1.6, 0.0, 1.0));
|
||||
c = c + vec3<f32>(0.35) * smoothstep(0.95, 0.99, cos(side * 3.0));
|
||||
}
|
||||
return out_color(vec4<f32>(min(c, vec3<f32>(1.0)), 1.0));
|
||||
}
|
||||
if (u.ana.x < 2.5) {
|
||||
let a = degrees(asin(clamp(dot(normalize(i.n), normalize(u.pull.xyz)), -1.0, 1.0)));
|
||||
var c = vec3<f32>(0.95, 0.80, 0.15);
|
||||
|
||||
@@ -652,6 +652,15 @@ pub fn paint(p: &Painter, r: Rect, name: &str, ink: Color32, fill: Color32, acce
|
||||
pen.line(&[(3.0 + 12.0 * t, 17.0 + 2.0 * t), (9.0 + 12.0 * t, 5.0 + 2.0 * t)], a);
|
||||
}
|
||||
}
|
||||
"environment_map" => {
|
||||
let pts: Vec<Pos2> =
|
||||
(0..32).map(|i| i as f32 / 32.0 * std::f32::consts::TAU).map(|t| pen.at(12.0 + 9.0 * t.cos(), 12.0 + 9.0 * t.sin())).collect();
|
||||
p.add(Shape::convex_polygon(pts, Color32::from_rgb(190, 205, 230), Stroke::new(pen.w, ink)));
|
||||
pen.poly(&[(3.6, 13.0), (20.4, 13.0), (18.5, 17.5), (5.5, 17.5)], Color32::from_rgb(60, 62, 70), Color32::TRANSPARENT);
|
||||
pen.line(&[(3.2, 12.6), (20.8, 12.6)], Color32::WHITE);
|
||||
p.circle_filled(pen.at(9.0, 8.0), 2.2 * pen.s(), Color32::WHITE);
|
||||
pen.circle(12.0, 12.0, 9.0, Color32::TRANSPARENT, ink);
|
||||
}
|
||||
"zebra" | "draft_analysis" | "curvature_map" => {
|
||||
let pts: Vec<Pos2> =
|
||||
(0..32).map(|i| i as f32 / 32.0 * std::f32::consts::TAU).map(|t| pen.at(12.0 + 9.0 * t.cos(), 12.0 + 9.0 * t.sin())).collect();
|
||||
|
||||
@@ -101,7 +101,11 @@ pub fn start_hook(app: &mut SolveApp, id: &str) -> bool {
|
||||
("FusionZebraAnalysisCommand", Some(A::Zebra { .. })) => Some(true),
|
||||
("FusionDraftAnalysisCommand", Some(A::Draft { .. })) => Some(true),
|
||||
("FusionCurvatureMapAnalysisCommand", Some(A::Curvature { .. })) => Some(true),
|
||||
("FusionZebraAnalysisCommand" | "FusionDraftAnalysisCommand" | "FusionCurvatureMapAnalysisCommand", _) => Some(false),
|
||||
("FusionEnvironmentMapAnalysisCommand", Some(A::Environment)) => Some(true),
|
||||
(
|
||||
"FusionZebraAnalysisCommand" | "FusionDraftAnalysisCommand" | "FusionCurvatureMapAnalysisCommand" | "FusionEnvironmentMapAnalysisCommand",
|
||||
_,
|
||||
) => Some(false),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(on) = same {
|
||||
|
||||
@@ -653,6 +653,7 @@ fn analysis_uniform(app: &SolveApp) -> [f32; 8] {
|
||||
Some(A::Zebra { stripes }) => [1.0, stripes as f32, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
|
||||
Some(A::Draft { pull, angle }) => [2.0, angle as f32, 0.0, 0.0, pull.x as f32, pull.y as f32, pull.z as f32, 0.0],
|
||||
Some(A::Curvature { radius }) => [3.0, radius as f32, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
|
||||
Some(A::Environment) => [4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
|
||||
None => [0.0; 8],
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user