Skip to content

Commit

Permalink
types for hyperbolic space (#420)
Browse files Browse the repository at this point in the history
Partial fix for #264

Adds `MVector` in math.rs generally for points and directions in hyperbolic space, replacing `na::Vector4` when appropriate
Adds `MIsometry` in math.rs representing hyperbolic isometries, replacing `na::Matrix4` when appropriate

Authored-by: strawberry <[email protected]>
  • Loading branch information
strawberrycinnabar authored Jul 28, 2024
1 parent d49df99 commit e80465d
Show file tree
Hide file tree
Showing 22 changed files with 769 additions and 471 deletions.
7 changes: 3 additions & 4 deletions client/src/graphics/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use metrics::histogram;
use super::{fog, voxels, Base, Fog, Frustum, GltfScene, Meshes, Voxels};
use crate::{Asset, Config, Loader, Sim};
use common::proto::{Character, Position};
use common::{math, SimConfig};
use common::SimConfig;

/// Manages rendering, independent of what is being rendered to
pub struct Draw {
Expand Down Expand Up @@ -289,7 +289,7 @@ impl Draw {
let draw_started = Instant::now();
let view = sim.as_ref().map_or_else(Position::origin, |sim| sim.view());
let projection = frustum.projection(1.0e-4);
let view_projection = projection.matrix() * math::mtranspose(&view.local);
let view_projection = projection.matrix() * na::Matrix4::from(view.local.mtranspose());
self.loader.drive();

let device = &*self.gfx.device;
Expand Down Expand Up @@ -482,8 +482,7 @@ impl Draw {
.expect("positionless entity in graph");
if let Some(character_model) = self.loader.get(self.character_model) {
if let Ok(ch) = sim.world.get::<&Character>(entity) {
let transform = transform
* pos.local
let transform = na::Matrix4::from(transform * pos.local)
* na::Matrix4::new_scaling(sim.cfg().meters_to_absolute)
* ch.state.orientation.to_homogeneous();
for mesh in &character_model.0 {
Expand Down
37 changes: 28 additions & 9 deletions client/src/graphics/frustum.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use common::math::MVector;
use common::Plane;

#[derive(Debug, Copy, Clone)]
Expand Down Expand Up @@ -79,7 +80,7 @@ pub struct FrustumPlanes {
}

impl FrustumPlanes {
pub fn contain(&self, point: &na::Vector4<f32>, radius: f32) -> bool {
pub fn contain(&self, point: &MVector<f32>, radius: f32) -> bool {
for &plane in &[&self.left, &self.right, &self.down, &self.up] {
if plane.distance_to(point) < -radius {
return false;
Expand All @@ -92,20 +93,38 @@ impl FrustumPlanes {
#[cfg(test)]
mod tests {
use super::*;
use common::math::{origin, translate_along};
use common::math::translate_along;
use std::f32;

#[test]
fn planes_sanity() {
// 90 degree square
let planes = Frustum::from_vfov(f32::consts::FRAC_PI_4, 1.0).planes();
assert!(planes.contain(&origin(), 0.1));
assert!(planes.contain(&(translate_along(&-na::Vector3::z()) * origin()), 0.0));
assert!(!planes.contain(&(translate_along(&na::Vector3::z()) * origin()), 0.0));
assert!(planes.contain(&MVector::origin(), 0.1));
assert!(planes.contain(
&(translate_along(&-na::Vector3::z()) * MVector::origin()),
0.0
));
assert!(!planes.contain(
&(translate_along(&na::Vector3::z()) * MVector::origin()),
0.0
));

assert!(!planes.contain(&(translate_along(&na::Vector3::x()) * origin()), 0.0));
assert!(!planes.contain(&(translate_along(&na::Vector3::y()) * origin()), 0.0));
assert!(!planes.contain(&(translate_along(&-na::Vector3::x()) * origin()), 0.0));
assert!(!planes.contain(&(translate_along(&-na::Vector3::y()) * origin()), 0.0));
assert!(!planes.contain(
&(translate_along(&na::Vector3::x()) * MVector::origin()),
0.0
));
assert!(!planes.contain(
&(translate_along(&na::Vector3::y()) * MVector::origin()),
0.0
));
assert!(!planes.contain(
&(translate_along(&-na::Vector3::x()) * MVector::origin()),
0.0
));
assert!(!planes.contain(
&(translate_along(&-na::Vector3::y()) * MVector::origin()),
0.0
));
}
}
12 changes: 6 additions & 6 deletions client/src/graphics/voxels/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use common::{
dodeca::Vertex,
graph::NodeId,
lru_slab::SlotId,
math,
math::{MIsometry, MVector},
node::{Chunk, ChunkId, VoxelData},
LruSlab,
};
Expand Down Expand Up @@ -88,7 +88,7 @@ impl Voxels {
device: &Device,
frame: &mut Frame,
sim: &mut Sim,
nearby_nodes: &[(NodeId, na::Matrix4<f32>)],
nearby_nodes: &[(NodeId, MIsometry<f32>)],
cmd: vk::CommandBuffer,
frustum: &Frustum,
) {
Expand Down Expand Up @@ -122,12 +122,12 @@ impl Voxels {
}
let node_scan_started = Instant::now();
let frustum_planes = frustum.planes();
let local_to_view = math::mtranspose(&view.local);
let local_to_view = view.local.mtranspose();
let mut extractions = Vec::new();
let mut workqueue_is_full = false;
for &(node, ref node_transform) in nearby_nodes {
let node_to_view = local_to_view * node_transform;
let origin = node_to_view * math::origin();
let node_to_view = local_to_view * *node_transform;
let origin = node_to_view * MVector::origin();
if !frustum_planes.contain(&origin, dodeca::BOUNDING_SPHERE_RADIUS) {
// Don't bother generating or drawing chunks from nodes that are wholly outside the
// frustum.
Expand Down Expand Up @@ -174,7 +174,7 @@ impl Voxels {
frame.drawn.push(slot);
// Transfer transform
frame.surface.transforms_mut()[slot.0 as usize] =
node_transform * vertex.chunk_to_node();
na::Matrix4::from(*node_transform) * vertex.chunk_to_node();
}
if let (None, &VoxelData::Dense(ref data)) = (&surface, voxels) {
// Extract a surface so it can be drawn in future frames
Expand Down
5 changes: 3 additions & 2 deletions client/src/local_character_controller.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use common::{math, proto::Position};
use common::{math, math::MIsometry, proto::Position};

pub struct LocalCharacterController {
/// The last extrapolated inter-frame view position, used for rendering and gravity-specific
Expand All @@ -25,7 +25,8 @@ impl LocalCharacterController {
pub fn oriented_position(&self) -> Position {
Position {
node: self.position.node,
local: self.position.local * self.orientation.to_homogeneous(),
local: self.position.local
* MIsometry::unit_quaternion_to_homogeneous(self.orientation),
}
}

Expand Down
3 changes: 2 additions & 1 deletion client/src/prediction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,13 @@ impl PredictedMotion {
#[cfg(test)]
mod tests {
use super::*;
use common::math::MIsometry;

/// An arbitrary position
fn pos() -> Position {
Position {
node: common::graph::NodeId::ROOT,
local: na::one(),
local: MIsometry::identity(),
}
}

Expand Down
12 changes: 6 additions & 6 deletions client/src/sim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use common::{
character_controller,
collision_math::Ray,
graph::{Graph, NodeId},
graph_ray_casting,
graph_ray_casting, math,
math::{MIsometry, MVector},
node::{populate_fresh_nodes, ChunkId, VoxelData},
proto::{
self, BlockUpdate, Character, CharacterInput, CharacterState, Command, Component,
Expand Down Expand Up @@ -109,7 +110,7 @@ impl Sim {
selected_material: Material::WoodPlanks,
prediction: PredictedMotion::new(proto::Position {
node: NodeId::ROOT,
local: na::one(),
local: MIsometry::identity(),
}),
local_character_controller: LocalCharacterController::new(),
}
Expand Down Expand Up @@ -510,9 +511,8 @@ impl Sim {
pub fn view(&self) -> Position {
let mut pos = self.local_character_controller.oriented_position();
let up = self.graph.get_relative_up(&pos).unwrap();
pos.local *= common::math::translate_along(
&(up.as_ref() * (self.cfg.character.character_radius - 1e-3)),
);
pos.local *=
math::translate_along(&(up.as_ref() * (self.cfg.character.character_radius - 1e-3)));
pos
}

Expand Down Expand Up @@ -550,7 +550,7 @@ impl Sim {
let ray_casing_result = graph_ray_casting::ray_cast(
&self.graph,
&view_position,
&Ray::new(na::Vector4::w(), -na::Vector4::z()),
&Ray::new(MVector::w(), -MVector::z()),
self.cfg.character.block_reach,
);

Expand Down
19 changes: 14 additions & 5 deletions common/src/character_controller/collision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

use tracing::error;

use crate::{collision_math::Ray, graph::Graph, graph_collision, math, proto::Position};
use crate::{
collision_math::Ray,
graph::Graph,
graph_collision, math,
math::{MIsometry, MVector},
proto::Position,
};

/// Checks for collisions when a character moves with a character-relative displacement vector of `relative_displacement`.
pub fn check_collision(
Expand All @@ -22,7 +28,10 @@ pub fn check_collision(
let displacement_norm = displacement_sqr.sqrt();
let displacement_normalized = relative_displacement / displacement_norm;

let ray = Ray::new(math::origin(), displacement_normalized);
let ray = Ray::new(
MVector::origin(),
MVector::<f32>::from(displacement_normalized),
);
let tanh_distance = displacement_norm.tanh();

let cast_hit = graph_collision::sphere_cast(
Expand Down Expand Up @@ -58,7 +67,7 @@ pub fn check_collision(
// This normal now represents a contact point at the origin, so we omit the w-coordinate
// to ensure that it's orthogonal to the origin.
normal: na::UnitVector3::new_normalize(
(math::mtranspose(&displacement_transform) * hit.normal).xyz(),
(displacement_transform.mtranspose() * hit.normal).xyz(),
),
}),
}
Expand All @@ -77,7 +86,7 @@ pub struct CollisionCheckingResult {

/// Multiplying the character's position by this matrix will move the character as far as it can up to its intended
/// displacement until it hits the wall.
pub displacement_transform: na::Matrix4<f32>,
pub displacement_transform: MIsometry<f32>,

pub collision: Option<Collision>,
}
Expand All @@ -88,7 +97,7 @@ impl CollisionCheckingResult {
pub fn stationary() -> CollisionCheckingResult {
CollisionCheckingResult {
displacement_vector: na::Vector3::zeros(),
displacement_transform: na::Matrix4::identity(),
displacement_transform: MIsometry::identity(),
collision: None,
}
}
Expand Down
2 changes: 1 addition & 1 deletion common/src/character_controller/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub fn run_character_step(
}

// Renormalize
position.local = math::renormalize_isometry(&position.local);
position.local = position.local.renormalize_isometry();
let (next_node, transition_xf) = graph.normalize_transform(position.node, &position.local);
if next_node != position.node {
position.node = next_node;
Expand Down
Loading

0 comments on commit e80465d

Please sign in to comment.