Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 20 additions & 23 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions crates/re_viewer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,11 @@ rand = { version = "0.8", features = ["small_rng"] }
rfd = "0.8"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# We use bleeding edge three-d from 2022-05-22
three-d = { git = "https://github.com/asny/three-d", rev = "43f210668197e8b1dc50ea9f074d2b8426ecb0f2", default-features = false, features = [
"gltf-io",
"obj-io",
three-d = { version = "0.12.2", default-features = false }
three-d-asset = { version = "0.1.0", default-features = false, features = [
"gltf",
"image",
"obj",
] }
tracing = "0.1"
vec1 = "1.8"
Expand Down
60 changes: 32 additions & 28 deletions crates/re_viewer/src/misc/mesh_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub struct CpuMesh {

pub struct GpuMesh {
pub name: String,
pub models: Vec<InstancedModel<PhysicalMaterial>>,
pub meshes: Vec<Gm<InstancedMesh, PhysicalMaterial>>,
// pub materials: Vec<PhysicalMaterial>,
}

Expand All @@ -26,16 +26,22 @@ impl CpuMesh {

pub fn load_raw(name: String, format: MeshFormat, bytes: &[u8]) -> anyhow::Result<Self> {
crate::profile_function!();
let path = "mesh";
let mut loaded = three_d::io::Loaded::new();
loaded.insert_bytes(path, bytes.to_vec());

let (mut meshes, materials) = match format {
MeshFormat::Glb | MeshFormat::Gltf => loaded.gltf(path),
MeshFormat::Obj => loaded.obj(path),
}
.map_err(to_anyhow)
.with_context(|| format!("loading {format:?}"))?;
let path = match format {
MeshFormat::Glb => "mesh.glb",
MeshFormat::Gltf => "mesh.gltf",
MeshFormat::Obj => "mesh.obj",
};

let mut loaded = three_d_asset::io::RawAssets::new();
loaded.insert(path, bytes.to_vec());

let three_d::CpuModel {
geometries: mut meshes,
materials,
} = loaded
.deserialize(path)
.with_context(|| format!("loading {format:?}"))?;

for mesh in &mut meshes {
if mesh.tangents.is_none() {
Expand Down Expand Up @@ -67,7 +73,6 @@ impl CpuMesh {
let root_transform = three_d::Mat4::from_cols(c0.into(), c1.into(), c2.into(), c3.into());
for mesh in &mut slf.meshes {
mesh.transform(&root_transform)
.map_err(to_anyhow)
.context("Bad object transform")?;
}

Expand All @@ -86,8 +91,8 @@ impl CpuMesh {

let mut mesh = three_d::CpuMesh {
name: name.clone(),
positions: three_d::Positions::F32(positions),
indices: Some(three_d::Indices::U32(
positions: three_d_asset::Positions::F32(positions),
indices: Some(three_d_asset::Indices::U32(
indices.iter().flat_map(|triangle| *triangle).collect(),
)),
material_name: Some(material_name.clone()),
Expand Down Expand Up @@ -124,47 +129,46 @@ impl CpuMesh {

let mut materials = Vec::new();
for m in &self.materials {
materials.push(PhysicalMaterial::new(three_d, m).map_err(to_anyhow)?);
materials.push(PhysicalMaterial::new(three_d, m).map_err(|err| anyhow!("{}", err))?);
}

let mut models = Vec::new();
for m in &self.meshes {
let mut meshes = Vec::new();
for mesh in &self.meshes {
let material = materials
.iter()
.find(|material| Some(&material.name) == m.material_name.as_ref())
.find(|material| Some(&material.name) == mesh.material_name.as_ref())
.context("missing material")?
.clone();

let m = InstancedModel::new_with_material(three_d, &Default::default(), m, material)
.map_err(to_anyhow)?;
models.push(m);
let gm = Gm::new(
InstancedMesh::new(three_d, &Default::default(), mesh)
.map_err(|err| anyhow!("{}", err))?,
material,
);
meshes.push(gm);
}

Ok(GpuMesh {
name: self.name.clone(),
models,
meshes,
// materials,
})
}
}

#[allow(clippy::needless_pass_by_value)]
fn to_anyhow(err: Box<dyn std::error::Error>) -> anyhow::Error {
anyhow!("{}", err)
}

fn bbox(meshes: &[three_d::CpuMesh]) -> macaw::BoundingBox {
let mut bbox = macaw::BoundingBox::nothing();
for mesh in meshes {
match &mesh.positions {
three_d::Positions::F32(positions) => {
for pos in positions {
bbox.extend(glam::Vec3::from(pos.as_array()));
bbox.extend(glam::vec3(pos.x, pos.y, pos.z));
}
}
three_d::Positions::F64(positions) => {
for pos in positions {
bbox.extend(glam::Vec3::from(pos.cast::<f32>().unwrap().as_array()));
let pos = pos.cast::<f32>().unwrap();
bbox.extend(glam::vec3(pos.x, pos.y, pos.z));
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/re_viewer/src/ui/view3d/mesh_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl GpuMeshCache {
instances: &three_d::Instances,
) -> three_d::ThreeDResult<()> {
if let Some(Some(gpu_mesh)) = self.0.get_mut(&mesh_id) {
for model in &mut gpu_mesh.models {
for model in &mut gpu_mesh.meshes {
model.set_instances(instances)?;
}
}
Expand Down
53 changes: 29 additions & 24 deletions crates/re_viewer/src/ui/view3d/rendering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,15 @@ pub struct RenderingContext {

/// So we don't need to re-allocate them.
points_cache: sphere_renderer::InstancedSpheres<three_d::PhysicalMaterial>,
lines_cache: three_d::InstancedModel<LineMaterial>,
lines_cache: three_d::Gm<three_d::InstancedMesh, LineMaterial>,
}

impl RenderingContext {
pub fn new(gl: &std::sync::Arc<glow::Context>) -> three_d::ThreeDResult<Self> {
let three_d = three_d::Context::from_gl_context(gl.clone())?;

let skybox_dark =
three_d::Skybox::new(&three_d, &load_skybox_texture(skybox_dark)).unwrap();
let skybox_light =
three_d::Skybox::new(&three_d, &load_skybox_texture(skybox_light)).unwrap();
let skybox_dark = load_skybox_texture(&three_d, skybox_dark).unwrap();
let skybox_light = load_skybox_texture(&three_d, skybox_light).unwrap();

let ambient_light_intensity = 5.0;
let ambient_dark = three_d::AmbientLight::new_with_environment(
Expand All @@ -51,13 +49,15 @@ impl RenderingContext {
)
.unwrap();

let lines_cache = three_d::InstancedModel::new_with_material(
&three_d,
&Default::default(),
&three_d::CpuMesh::cylinder(10),
let lines_cache = three_d::Gm::new(
three_d::InstancedMesh::new(
&three_d,
&Default::default(),
&three_d::CpuMesh::cylinder(10),
)
.unwrap(),
Default::default(),
)
.unwrap();
);

Ok(Self {
three_d,
Expand All @@ -72,7 +72,10 @@ impl RenderingContext {
}
}

fn load_skybox_texture(color_from_dir: fn(glam::Vec3) -> [u8; 3]) -> three_d::CpuTextureCube {
fn load_skybox_texture(
three_d: &three_d::Context,
color_from_dir: fn(glam::Vec3) -> [u8; 3],
) -> three_d::ThreeDResult<three_d::Skybox> {
crate::profile_function!();

let resolution = 64;
Expand All @@ -89,14 +92,7 @@ fn load_skybox_texture(color_from_dir: fn(glam::Vec3) -> [u8; 3]) -> three_d::Cp
let e = generate_skybox_side(resolution, color_from_dir, Z, X, -Y);
let f = generate_skybox_side(resolution, color_from_dir, -Z, -X, -Y);

let data = three_d::TextureCubeData::RgbU8(a, b, c, d, e, f);

three_d::CpuTextureCube {
data,
width: resolution as _,
height: resolution as _,
..Default::default()
}
three_d::Skybox::new(three_d, &a, &b, &c, &d, &e, &f)
}

fn generate_skybox_side(
Expand All @@ -105,8 +101,8 @@ fn generate_skybox_side(
center_dir: glam::Vec3,
x_dir: glam::Vec3,
y_dir: glam::Vec3,
) -> Vec<[u8; 3]> {
(0..resolution)
) -> three_d::CpuTexture {
let data: Vec<[u8; 3]> = (0..resolution)
.flat_map(|y| {
let ty = egui::remap_clamp(y as f32, 0.0..=(resolution as f32 - 1.0), -1.0..=1.0);
(0..resolution).map(move |x| {
Expand All @@ -116,7 +112,16 @@ fn generate_skybox_side(
color_from_dir(dir)
})
})
.collect()
.collect();

three_d::CpuTexture {
data: three_d::TextureData::RgbU8(data),
width: resolution as _,
height: resolution as _,
wrap_s: three_d::Wrapping::ClampToEdge,
wrap_t: three_d::Wrapping::ClampToEdge,
..Default::default()
}
}

/// Color from view direction
Expand Down Expand Up @@ -321,7 +326,7 @@ pub fn paint_with_three_d(

for &mesh_id in mesh_instances.keys() {
if let Some(gpu_mesh) = rendering.gpu_mesh_cache.get(mesh_id) {
for obj in &gpu_mesh.models {
for obj in &gpu_mesh.meshes {
if obj.instance_count() > 0 {
objects.push(obj);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ impl InstancedSperesGeom {

for pos in &self.instances.translations_and_scale {
let radius = glam::Vec3A::splat(pos.w);
let pos = glam::Vec3A::from_slice(&pos.as_array());
let pos = glam::Vec3A::new(pos.x, pos.y, pos.z);
min = min.min(pos - radius);
max = max.max(pos + radius);
}
Expand Down