Skip to content

Commit

Permalink
Add tracer path lines instead of point sequences
Browse files Browse the repository at this point in the history
  • Loading branch information
joshburkart committed Jul 6, 2024
1 parent e6d87f6 commit 439a3d8
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 113 deletions.
72 changes: 23 additions & 49 deletions tsunami/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,20 @@ pub async fn run() {
),
);

let mut point_mesh = CpuMesh::sphere(10);
point_mesh.transform(&Mat4::from_scale(0.002)).unwrap();
let point_size = 0.002;
let point_mesh = {
let mut point_mesh = CpuMesh::sphere(10);
point_mesh.transform(&Mat4::from_scale(point_size)).unwrap();
point_mesh
};
let line_mesh = {
let mut line_mesh = CpuMesh::cylinder(10);
line_mesh
.transform(&Mat4::from_nonuniform_scale(1., point_size, point_size))
.unwrap();
line_mesh
};

let mut quadrature_point_cloud_model = Gm {
geometry: InstancedMesh::new(
&context,
Expand All @@ -250,7 +262,7 @@ pub async fn run() {
),
material: ColorMaterial::default(),
};
let mut tracer_point_cloud_model = Gm {
let mut tracers_model = Gm {
geometry: InstancedMesh::new(
&context,
&PointCloud {
Expand Down Expand Up @@ -390,7 +402,7 @@ pub async fn run() {
None,
);

if let param::ShowPoints::Quadrature = params.visualization.show_points {
if let param::ShowFeatures::Quadrature = params.visualization.show_features {
quadrature_point_cloud_model.geometry = InstancedMesh::new(
&context,
&PointCloud {
Expand All @@ -417,51 +429,13 @@ pub async fn run() {
quadrature_point_cloud_model.material.render_states.cull = Cull::FrontAndBack;
}

if let param::ShowPoints::Tracer = params.visualization.show_points {
tracer_point_cloud_model.geometry = InstancedMesh::new(
&context,
&PointCloud {
positions: Positions::F32(
rendering_data
.tracer_points
.points
.into_iter()
.map(|point| {
rotation.transform_vector(Vector3 {
x: point.x as f32,
y: point.y as f32,
z: point.z as f32,
})
})
.collect(),
),
colors: Some(
rendering_data
.tracer_points
.positions
.into_iter()
.map(|position| {
Srgba::new(
u8::MAX,
u8::MAX,
u8::MAX,
// Add transparency based on position in tracer's trail.
(u8::MAX as Float
* (position as Float
/ geom::TRACER_TAIL_LENGTH as Float)
.powf(0.25))
as u8,
)
})
.collect(),
),
}
.into(),
&point_mesh,
);
tracer_point_cloud_model.material.render_states.cull = Cull::None;
if let param::ShowFeatures::Tracers = params.visualization.show_features {
tracers_model.geometry = rendering_data
.tracer_points
.make_mesh(&context, &line_mesh, point_size, &rotation);
tracers_model.material.render_states.cull = Cull::None;
} else {
tracer_point_cloud_model.material.render_states.cull = Cull::FrontAndBack;
tracers_model.material.render_states.cull = Cull::FrontAndBack;
}
}

Expand Down Expand Up @@ -642,7 +616,7 @@ pub async fn run() {
std::iter::empty()
.chain(&mesh_model)
.chain(&quadrature_point_cloud_model)
.chain(&tracer_point_cloud_model)
.chain(&tracers_model)
.chain(&tsunami_hint_circle_object)
.chain(&moon_sprite_object)
.chain(&skybox),
Expand Down
22 changes: 11 additions & 11 deletions tsunami/src/param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl Default for PhysicsParameters {
pub struct VisualizationParameters {
pub height_exaggeration_factor: Float,
pub velocity_exaggeration_factor: Float,
pub show_points: ShowPoints,
pub show_features: ShowFeatures,
pub show_rotation: ShowRotation,
}

Expand All @@ -182,7 +182,7 @@ impl VisualizationParameters {
.text("velocity exaggeration")
.suffix("×"),
);
self.show_points.generate_ui(ui);
self.show_features.generate_ui(ui);
self.show_rotation.generate_ui(ui);
ui.add_space(10.);
}
Expand All @@ -193,7 +193,7 @@ impl Default for VisualizationParameters {
Self {
height_exaggeration_factor: 500.,
velocity_exaggeration_factor: 1.5e3,
show_points: ShowPoints::Tracer,
show_features: ShowFeatures::Tracers,
show_rotation: ShowRotation::None,
}
}
Expand Down Expand Up @@ -311,31 +311,31 @@ impl Default for Parameters {
}

#[derive(Copy, Clone, Debug, PartialEq, strum::EnumIter)]
pub enum ShowPoints {
pub enum ShowFeatures {
Quadrature,
Tracer,
Tracers,
None,
}

impl ShowPoints {
impl ShowFeatures {
fn generate_ui(&mut self, ui: &mut egui::Ui) {
ui.horizontal(|ui| {
use strum::IntoEnumIterator;

for value in Self::iter() {
ui.radio_value(self, value, value.to_string());
}
ui.label("show points");
ui.label("show");
});
}
}

impl std::fmt::Display for ShowPoints {
impl std::fmt::Display for ShowFeatures {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
ShowPoints::Quadrature => "quadrature",
ShowPoints::Tracer => "tracer",
ShowPoints::None => "none",
ShowFeatures::Quadrature => "quadrature points",
ShowFeatures::Tracers => "path lines",
ShowFeatures::None => "none",
})
}
}
Expand Down
175 changes: 122 additions & 53 deletions tsunami/src/render.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use flow::{float_consts, Float};
use ndarray as nd;
use three_d::{CpuMesh, Indices, Positions, Vector3};
use three_d::*;

#[derive(Clone)]
pub struct RenderingData {
pub quadrature_points: Vec<Vector3<Float>>,
pub tracer_points: TracerPoints,
pub tracer_points: Tracers,
pub mesh: CpuMesh,
}

Expand Down Expand Up @@ -131,7 +131,7 @@ impl SphereRenderable {

RenderingData {
quadrature_points,
tracer_points: self.make_tracer_points(height_exaggeration_factor),
tracer_points: self.make_tracers(height_exaggeration_factor),
mesh,
}
}
Expand All @@ -147,31 +147,34 @@ impl SphereRenderable {
points
}

fn make_tracer_points(&self, height_exaggeration_factor: Float) -> TracerPoints {
let (points, positions) = self
fn make_tracers(&self, height_exaggeration_factor: Float) -> Tracers {
if self.tracer_points_history_theta_phi.is_empty() {
return Tracers::new(Vec::new());
}

let mut path_lines: Vec<_> =
(0..self.tracer_points_history_theta_phi.first().unwrap().len())
.map(|_| Vec::with_capacity(self.tracer_points_history_theta_phi.len()))
.collect();
for (tracer_points_theta_phi, tracer_heights) in self
.tracer_points_history_theta_phi
.iter()
.enumerate()
.zip(&self.tracer_heights_history)
.map(|((position, tracer_points_theta_phi), tracer_heights)| {
tracer_points_theta_phi
.axis_iter(nd::Axis(1))
.zip(tracer_heights.iter())
.map(move |(point_theta_phi, &height)| {
(
self.make_point(
point_theta_phi[[flow::bases::ylm::Component::Theta as usize]],
point_theta_phi[[flow::bases::ylm::Component::Phi as usize]],
height,
height_exaggeration_factor,
),
position,
)
})
})
.flatten()
.unzip();
TracerPoints { points, positions }
.zip(self.tracer_heights_history.iter())
{
for (j, (tracer_point_theta_phi, &tracer_height)) in tracer_points_theta_phi
.axis_iter(nd::Axis(1))
.zip(tracer_heights.iter())
.enumerate()
{
path_lines[j].push(self.make_point(
tracer_point_theta_phi[[flow::bases::ylm::Component::Theta as usize]],
tracer_point_theta_phi[[flow::bases::ylm::Component::Phi as usize]],
tracer_height,
height_exaggeration_factor,
));
}
}
Tracers::new(path_lines)
}

fn make_point(
Expand Down Expand Up @@ -279,7 +282,7 @@ impl TorusRenderable {

RenderingData {
quadrature_points,
tracer_points: self.make_tracer_points(height_exaggeration_factor),
tracer_points: self.make_tracers(height_exaggeration_factor),
mesh,
}
}
Expand All @@ -295,31 +298,34 @@ impl TorusRenderable {
points
}

fn make_tracer_points(&self, height_exaggeration_factor: Float) -> TracerPoints {
let (points, positions) = self
fn make_tracers(&self, height_exaggeration_factor: Float) -> Tracers {
if self.tracer_points_history_theta_phi.is_empty() {
return Tracers::new(Vec::new());
}

let mut path_lines: Vec<_> =
(0..self.tracer_points_history_theta_phi.first().unwrap().len())
.map(|_| Vec::with_capacity(self.tracer_points_history_theta_phi.len()))
.collect();
for (tracer_points_theta_phi, tracer_heights) in self
.tracer_points_history_theta_phi
.iter()
.enumerate()
.zip(&self.tracer_heights_history)
.map(|((position, tracer_points_theta_phi), tracer_heights)| {
tracer_points_theta_phi
.axis_iter(nd::Axis(1))
.zip(tracer_heights.iter())
.map(move |(point_theta_phi, &height)| {
(
self.make_point(
point_theta_phi[[0]],
point_theta_phi[[1]],
height,
height_exaggeration_factor,
),
position,
)
})
})
.flatten()
.unzip();
TracerPoints { points, positions }
.zip(self.tracer_heights_history.iter())
{
for (j, (tracer_point_theta_phi, &tracer_height)) in tracer_points_theta_phi
.axis_iter(nd::Axis(1))
.zip(tracer_heights.iter())
.enumerate()
{
path_lines[j].push(self.make_point(
tracer_point_theta_phi[[flow::bases::ylm::Component::Theta as usize]],
tracer_point_theta_phi[[flow::bases::ylm::Component::Phi as usize]],
tracer_height,
height_exaggeration_factor,
));
}
}
Tracers::new(path_lines)
}

fn make_point(
Expand All @@ -340,7 +346,70 @@ impl TorusRenderable {
}

#[derive(Clone)]
pub struct TracerPoints {
pub points: Vec<Vector3<Float>>,
pub positions: Vec<usize>,
pub struct Tracers {
path_lines: Vec<Vec<Vector3<Float>>>,
}

impl Tracers {
pub fn new(path_lines: Vec<Vec<Vector3<Float>>>) -> Self {
Self { path_lines }
}

pub fn make_mesh(
&self,
context: &three_d::Context,
line_mesh: &three_d::CpuMesh,
line_width: f32,
rotation: &three_d::Mat4,
) -> three_d::InstancedMesh {
let (transformations, colors) = self
.path_lines
.iter()
.map(|path_line| {
path_line
.iter()
.zip(path_line.iter().skip(1))
.enumerate()
.map(|(position, (start, end))| {
let start = Vec3::new(start.x as f32, start.y as f32, start.z as f32);
let end = Vec3::new(end.x as f32, end.y as f32, end.z as f32);
let displacement = end - start;
let length = displacement.magnitude();
let axis = Vec3::unit_x().cross(displacement).normalize();
let angle = displacement.angle(Vec3::unit_x());

let direction_rotation = Mat4::from_axis_angle(axis, angle);
let length_scale = Mat4::from_nonuniform_scale(length, 1., 1.);

// Add transparency based on position in tracer's trail and length of line
// segment.
let opacity = (4. * length
/ (crate::geom::TRACER_TAIL_LENGTH as f32 * line_width))
.min(1.)
* (position as f32 / crate::geom::TRACER_TAIL_LENGTH as f32);
let color =
Srgba::new(u8::MAX, u8::MAX, u8::MAX, (u8::MAX as f32 * opacity) as u8);

(
rotation
* Mat4::from_translation(start)
* direction_rotation
* length_scale,
color,
)
})
})
.flatten()
.unzip();

InstancedMesh::new(
context,
&Instances {
transformations,
colors: Some(colors),
texture_transformations: None,
},
line_mesh,
)
}
}

0 comments on commit 439a3d8

Please sign in to comment.