forked from 1b-agent/opencadstudio-upstream
Expand GPU analytical curves to interactive previews and transformations
This commit is contained in:
1 parent
84e95e4781
commit
ec3b6b89f6
8 files changed
+464
-19
No files matched your search
@@ -237,7 +237,7 @@ pub fn extract_circle_instance_from_geom(
|
||||
),
|
||||
_ => return None,
|
||||
};
|
||||
if radius <= 0.0 || !radius.is_finite() || !start_angle.is_finite() || !end_angle.is_finite() {
|
||||
if radius <= 0.0 || !radius.is_finite() || !start_angle.is_finite() || !end_angle.is_finite() || radius > 1e6 {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ pub fn extract_ellipse_instance_from_geom(
|
||||
|
||||
let major_len_sq = major_axis[0] * major_axis[0] + major_axis[1] * major_axis[1] + major_axis[2] * major_axis[2];
|
||||
let norm_len_sq = normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2];
|
||||
if major_len_sq <= 1e-12 || !major_len_sq.is_finite()
|
||||
if major_len_sq <= 1e-12 || !major_len_sq.is_finite() || major_len_sq > 1e12
|
||||
|| norm_len_sq <= 1e-12 || !norm_len_sq.is_finite()
|
||||
|| minor_axis_ratio <= 1e-6 || !minor_axis_ratio.is_finite()
|
||||
|| !start_param.is_finite() || !end_param.is_finite()
|
||||
|
||||
@@ -273,6 +273,8 @@ pub struct Pipeline {
|
||||
/// frame they are present (small), drawn on top of the base wire pass — so
|
||||
/// a live drag never re-uploads the resident base buffer.
|
||||
gpu_preview_wires: Vec<WireGpu>,
|
||||
gpu_preview_circles: Vec<CircleGpu>,
|
||||
gpu_preview_ellipses: Vec<EllipseGpu>,
|
||||
/// Wipeout masks — solid fills rendered after wires in a separate pass via
|
||||
/// the legacy per-primitive `WipeoutGpu` renderer.
|
||||
gpu_wipeouts: Vec<WipeoutGpu>,
|
||||
@@ -2346,6 +2348,8 @@ impl Pipeline {
|
||||
gpu_selected_ellipses: vec![],
|
||||
gpu_selected_block_wires: vec![],
|
||||
gpu_preview_wires: vec![],
|
||||
gpu_preview_circles: vec![],
|
||||
gpu_preview_ellipses: vec![],
|
||||
gpu_wipeouts: vec![],
|
||||
wipeout_skip_flags: vec![],
|
||||
gpu_images: vec![],
|
||||
@@ -2940,11 +2944,47 @@ impl Pipeline {
|
||||
wires: &[WireModel],
|
||||
depth_map: &rustc_hash::FxHashMap<u64, [f32; 2]>,
|
||||
) {
|
||||
self.gpu_preview_wires = if wires.is_empty() {
|
||||
vec![]
|
||||
if wires.is_empty() {
|
||||
self.gpu_preview_wires.clear();
|
||||
self.gpu_preview_circles.clear();
|
||||
self.gpu_preview_ellipses.clear();
|
||||
} else {
|
||||
WireGpu::from_run(device, queue, wires, depth_map, false, self.wire_const_bgl.as_ref())
|
||||
};
|
||||
let partitioned = wire_arena::partition_wires(wires, depth_map);
|
||||
let mut non_analytical = partitioned.regular;
|
||||
non_analytical.extend(partitioned.mesh);
|
||||
self.gpu_preview_wires = if non_analytical.is_empty() {
|
||||
vec![]
|
||||
} else {
|
||||
WireGpu::from_run_refs(
|
||||
device,
|
||||
queue,
|
||||
&non_analytical,
|
||||
depth_map,
|
||||
false,
|
||||
self.wire_const_bgl.as_ref(),
|
||||
)
|
||||
};
|
||||
self.gpu_preview_circles = if partitioned.circle_instances.is_empty() {
|
||||
vec![]
|
||||
} else {
|
||||
vec![CircleGpu::from_instances(
|
||||
device,
|
||||
queue,
|
||||
"preview.circles",
|
||||
&partitioned.circle_instances,
|
||||
)]
|
||||
};
|
||||
self.gpu_preview_ellipses = if partitioned.ellipse_instances.is_empty() {
|
||||
vec![]
|
||||
} else {
|
||||
vec![EllipseGpu::from_instances(
|
||||
device,
|
||||
queue,
|
||||
"preview.ellipses",
|
||||
&partitioned.ellipse_instances,
|
||||
)]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Upload the live grip-drag / command-preview SDF glyph quads. Re-uploaded
|
||||
@@ -4611,6 +4651,24 @@ impl Pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.gpu_preview_circles.iter().any(|cg| cg.instance_count > 0) {
|
||||
pass.set_pipeline(&self.circle_xray_pipeline);
|
||||
for cg in &self.gpu_preview_circles {
|
||||
if cg.instance_count > 0 {
|
||||
pass.set_vertex_buffer(0, cg.instance_buffer.slice(..));
|
||||
pass.draw(0..6, 0..cg.instance_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.gpu_preview_ellipses.iter().any(|eg| eg.instance_count > 0) {
|
||||
pass.set_pipeline(&self.ellipse_xray_pipeline);
|
||||
for eg in &self.gpu_preview_ellipses {
|
||||
if eg.instance_count > 0 {
|
||||
pass.set_vertex_buffer(0, eg.instance_buffer.slice(..));
|
||||
pass.draw(0..6, 0..eg.instance_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Pass 5c: SDF text quads (drawn over wires) ────────────────────
|
||||
@@ -4970,6 +5028,8 @@ impl Pipeline {
|
||||
self.gpu_selected_circles.clear();
|
||||
self.gpu_selected_ellipses.clear();
|
||||
self.gpu_preview_wires.clear();
|
||||
self.gpu_preview_circles.clear();
|
||||
self.gpu_preview_ellipses.clear();
|
||||
self.hatch_gpu.clear();
|
||||
self.gpu_wipeouts.clear();
|
||||
self.wipeout_skip_flags.clear();
|
||||
|
||||
@@ -1644,4 +1644,48 @@ mod tests {
|
||||
assert!(blank_const().pattern_length < 0.0);
|
||||
assert!(blank_packed_instance().pattern_length < 0.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn partition_wires_partitions_preview_analytical_curves() {
|
||||
use crate::scene::model::wire_model::TangentGeom;
|
||||
let mut circle_preview = WireModel::default();
|
||||
circle_preview.tangent_geoms.push(TangentGeom::PlanarCircle {
|
||||
center: [1.0, 2.0, 3.0],
|
||||
axis_x: [1.0, 0.0, 0.0],
|
||||
axis_y: [0.0, 1.0, 0.0],
|
||||
radius: 10.0,
|
||||
});
|
||||
|
||||
let mut arc_preview = WireModel::default();
|
||||
arc_preview.tangent_geoms.push(TangentGeom::Arc {
|
||||
center: [4.0, 5.0, 6.0],
|
||||
axis_x: [1.0, 0.0, 0.0],
|
||||
axis_y: [0.0, 1.0, 0.0],
|
||||
radius: 8.0,
|
||||
start_angle: 0.1,
|
||||
end_angle: 2.0,
|
||||
});
|
||||
|
||||
let mut ellipse_preview = WireModel::default();
|
||||
ellipse_preview.tangent_geoms.push(TangentGeom::PlanarEllipse {
|
||||
center: [7.0, 8.0, 9.0],
|
||||
major_axis: [5.0, 0.0, 0.0],
|
||||
normal: [0.0, 0.0, 1.0],
|
||||
minor_axis_ratio: 0.6,
|
||||
start_param: 0.0,
|
||||
end_param: std::f64::consts::TAU,
|
||||
});
|
||||
|
||||
let mut regular_line = WireModel::default();
|
||||
regular_line.points.push([0.0, 0.0, 0.0]);
|
||||
regular_line.points.push([1.0, 1.0, 1.0]);
|
||||
|
||||
let wires = vec![circle_preview, arc_preview, ellipse_preview, regular_line];
|
||||
let depth_map = rustc_hash::FxHashMap::default();
|
||||
let partitioned = partition_wires(&wires, &depth_map);
|
||||
|
||||
assert_eq!(partitioned.circle_instances.len(), 2);
|
||||
assert_eq!(partitioned.ellipse_instances.len(), 1);
|
||||
assert_eq!(partitioned.regular.len(), 1);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user