Skip to content

Commit

Permalink
Rasmusgo/quadrics gallery (#443)
Browse files Browse the repository at this point in the history
  • Loading branch information
rasmusgo authored Aug 25, 2023
1 parent c898dd8 commit 92f622e
Show file tree
Hide file tree
Showing 14 changed files with 463 additions and 137 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: clippy
args: -- -D warnings
args: --tests -- -D warnings
- name: Run cargo clippy (android)
uses: actions-rs/cargo@v1
with:
Expand Down
201 changes: 156 additions & 45 deletions examples/custom-rendering/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod custom_render_context;
mod custom_rendering;
mod hologram;
mod surface_solver;

use custom_render_context::{create_quadrics_pipeline, CustomRenderContext};
use custom_rendering::custom_rendering_system;
Expand All @@ -10,8 +11,8 @@ use hotham::{
components::{
hand::Handedness, physics::SharedShape, Collider, Grabbable, LocalTransform, Mesh,
},
glam::{Mat4, Quat, Vec3},
hecs::World,
glam::{Mat4, Quat},
hecs::{Entity, World},
systems::{
animation_system, debug::debug_system, grabbing_system, hands::add_hand, hands_system,
physics_system, skinning::skinning_system, update_global_transform_system,
Expand All @@ -20,6 +21,7 @@ use hotham::{
xr, Engine, HothamResult, TickData,
};
use hotham_examples::navigation::{navigation_system, State};
use surface_solver::{surface_solver_system, ControlPoints, HologramBackside};

#[cfg_attr(target_os = "android", ndk_glue::main(backtrace = "on"))]
pub fn main() {
Expand Down Expand Up @@ -62,6 +64,7 @@ fn tick(
physics_system(engine);
animation_system(engine);
navigation_system(engine, state);
surface_solver_system(engine);
update_global_transform_system(engine);
skinning_system(engine);
debug_system(engine);
Expand Down Expand Up @@ -123,87 +126,179 @@ fn init(engine: &mut Engine) -> Result<(), hotham::HothamError> {
let vulkan_context = &mut engine.vulkan_context;
let world = &mut engine.world;

let mut glb_buffers: Vec<&[u8]> = vec![
let glb_buffers: Vec<&[u8]> = vec![
include_bytes!("../../../test_assets/left_hand.glb"),
include_bytes!("../../../test_assets/right_hand.glb"),
include_bytes!("../../../test_assets/sphere.glb"),
include_bytes!("../../../test_assets/hologram_templates.glb"),
];

#[cfg(target_os = "android")]
glb_buffers.push(include_bytes!(
"../../../test_assets/damaged_helmet_squished.glb"
));

#[cfg(not(target_os = "android"))]
glb_buffers.push(include_bytes!("../../../test_assets/damaged_helmet.glb"));

let models =
asset_importer::load_models_from_glb(&glb_buffers, vulkan_context, render_context)?;
add_helmet(&models, world, [-1., 1.4, -1.].into());
add_helmet(&models, world, [1., 1.4, -1.].into());
add_hand(&models, Handedness::Left, world);
add_hand(&models, Handedness::Right, world);
let uv1_from_local = Mat4::from_diagonal([1.0, 1.0, 1.0, 0.1].into());
let uv2_from_local = Mat4::from_cols_array(&[
1.0, 0.0, 0.0, 0.0, //
0.0, 0.0, 1.0, 0.0, //
0.0, 1.0, 0.0, 0.0, //
0.0, 0.0, 0.0, 0.1, //
]);
let uv3_from_local = Mat4::from_diagonal([0.0, 1.0, 0.0, 0.1].into());
add_quadric(
&models,
"Sphere",
world,
&LocalTransform {
translation: [1.0, 1.4, -1.5].into(),
rotation: Quat::IDENTITY,
scale: [0.5, 0.5, 0.5].into(),
},
&make_transform(-1.0, 1.4, -1.5, 0.5),
0.5,
HologramData {
// Sphere, x² + y² + z² = 1
surface_q_in_local: Mat4::from_diagonal([1.0, 1.0, 1.0, -1.0].into()),
bounds_q_in_local: Mat4::from_diagonal([0.0, 0.0, 0.0, 0.0].into()),
uv_from_local: Mat4::IDENTITY,
uv_from_local: uv1_from_local,
},
);
add_quadric(
&models,
"Cylinder",
world,
&LocalTransform {
translation: [-1.0, 1.4, -1.5].into(),
rotation: Quat::IDENTITY,
scale: [0.5, 0.5, 0.5].into(),
&make_transform(0.0, 1.4, -1.5, 0.5),
0.5_f32.sqrt(),
HologramData {
// Cylinder, x² + z² = 1
surface_q_in_local: Mat4::from_diagonal([1.0, 0.0, 1.0, -1.0].into()),
bounds_q_in_local: Mat4::from_diagonal([0.0, 1.0, 0.0, -1.0].into()),
uv_from_local: uv1_from_local,
},
0.5,
);
add_quadric(
&models,
"Cylinder",
world,
&make_transform(1.0, 1.4, -1.5, 0.5),
0.5_f32.sqrt(),
HologramData {
// Hyperboloid of one sheet, x² - y² + z² = c
surface_q_in_local: Mat4::from_diagonal([1.0, -1.0 + 0.1, 1.0, -0.1].into()),
bounds_q_in_local: Mat4::from_diagonal([0.0, 1.0, 0.0, -1.0].into()),
uv_from_local: uv2_from_local,
},
);
add_quadric(
&models,
"Cylinder",
world,
&make_transform(2.0, 1.4, -1.5, 0.5),
0.5_f32.sqrt(),
HologramData {
// Double cones, x² - y² + z² = 0
surface_q_in_local: Mat4::from_diagonal([1.0, -1.0, 1.0, 0.0].into()),
bounds_q_in_local: Mat4::from_diagonal([0.0, 1.0, 0.0, -1.0].into()),
uv_from_local: uv2_from_local,
},
);
add_quadric(
&models,
"Cylinder",
world,
&make_transform(3.0, 1.4, -1.5, 0.5),
0.5_f32.sqrt(),
HologramData {
// Hyperboloid of two sheets, x² - y² + z² = -c
surface_q_in_local: Mat4::from_diagonal([1.0, -1.0 - 0.1, 1.0, 0.1].into()),
bounds_q_in_local: Mat4::from_diagonal([0.0, 1.0, 0.0, -1.0].into()),
uv_from_local: uv2_from_local,
},
);
add_quadric(
&models,
"Cylinder",
world,
&make_transform(4.0, 1.4, -1.5, 0.5),
0.5_f32.sqrt(),
HologramData {
surface_q_in_local: Mat4::from_diagonal([1.0, 1.0, 0.0, -1.0].into()),
bounds_q_in_local: Mat4::from_diagonal([0.0, 0.0, 1.0, -1.0].into()),
uv_from_local: Mat4::IDENTITY,
// Hyperbolic paraboloid - "saddle", cy = x² + z²
surface_q_in_local: Mat4::from_cols(
[1.0, 0.0, 0.0, 0.0].into(),
[0.0, 0.0, 0.0, 1.0].into(),
[0.0, 0.0, -1.0, 0.0].into(),
[0.0, 1.0, 0.0, 0.0].into(),
),
bounds_q_in_local: Mat4::from_diagonal([1.0, 0.0, 1.0, -1.0].into()),
uv_from_local: uv2_from_local,
},
);

Ok(())
}
// Quadric surfaces with varying number of control points
let target_initial_hologram_data = HologramData {
surface_q_in_local: Mat4::from_diagonal([1.0, 1.0, 1.0, -1.0].into()),
bounds_q_in_local: Mat4::from_diagonal([1.0, 1.0, 1.0, -1.0].into()),
uv_from_local: uv2_from_local,
};
let t_from_local = Mat4::from_translation([0.0, -1.0, 0.0].into());
let t2_from_local = Mat4::from_translation([0.0, -0.5, 0.0].into());
let control_point_hologram_data = HologramData {
surface_q_in_local: t_from_local.transpose()
* Mat4::from_diagonal([1.0, -1.0, 1.0, 0.0].into())
* t_from_local,
bounds_q_in_local: t2_from_local.transpose()
* Mat4::from_diagonal([0.0, 1.0, 0.0, -0.25].into())
* t2_from_local,
uv_from_local: uv3_from_local,
};
for n in 1..=9 {
let target = add_quadric(
&models,
"Sphere",
world,
&make_transform(-2.0 + n as f32, 1.4, 1.5, 0.5),
0.5,
target_initial_hologram_data,
);

fn add_helmet(
models: &std::collections::HashMap<String, World>,
world: &mut World,
translation: Vec3,
) {
let helmet = add_model_to_world("Damaged Helmet", models, world, None)
.expect("Could not find Damaged Helmet");
let entities = (0..n)
.map(|i| {
add_quadric(
&models,
"Cylinder",
world,
&make_transform(
-2.0 + n as f32 + 0.1 * (i & 1) as f32,
1.4,
1.5 + 0.1 * (i >> 1) as f32,
0.05,
),
0.05,
control_point_hologram_data,
)
})
.collect();

{
let mut local_transform = world.get::<&mut LocalTransform>(helmet).unwrap();
local_transform.translation = translation;
local_transform.scale = [0.5, 0.5, 0.5].into();
let control_points = ControlPoints { entities };
world.insert_one(target, control_points).unwrap();
world.remove_one::<Grabbable>(target).unwrap();
}

let collider = Collider::new(SharedShape::ball(0.35));
Ok(())
}

world.insert(helmet, (collider, Grabbable {})).unwrap();
fn make_transform(x: f32, y: f32, z: f32, scale: f32) -> LocalTransform {
LocalTransform {
translation: [x, y, z].into(),
rotation: Quat::IDENTITY,
scale: [scale, scale, scale].into(),
}
}

fn add_quadric(
models: &std::collections::HashMap<String, World>,
model_name: &str,
world: &mut World,
local_transform: &LocalTransform,
ball_radius: f32,
hologram_data: HologramData,
) {
let entity = add_model_to_world("Sphere", models, world, None).expect("Could not find Sphere");
) -> Entity {
let entity = add_model_to_world(model_name, models, world, None)
.unwrap_or_else(|| panic!("Could not find {}", model_name));
*world.get::<&mut LocalTransform>(entity).unwrap() = *local_transform;
let collider = Collider::new(SharedShape::ball(ball_radius));
let hologram_component = Hologram {
Expand All @@ -214,4 +309,20 @@ fn add_quadric(
.insert(entity, (collider, Grabbable {}, hologram_component))
.unwrap();
world.remove_one::<Mesh>(entity).unwrap();

// Add second entity for the back surface
let second_entity = add_model_to_world(model_name, models, world, Some(entity))
.unwrap_or_else(|| panic!("Could not find {}", model_name));
// Negate Q to flip the surface normal
let mut hologram_component = hologram_component;
hologram_component.hologram_data.surface_q_in_local *= -1.0;
world
.insert(
second_entity,
(hologram_component, HologramBackside { entity }),
)
.unwrap();
world.remove_one::<Mesh>(second_entity).unwrap();

entity
}
Loading

0 comments on commit 92f622e

Please sign in to comment.