Skip to content

Commit 7336118

Browse files
patowenRalith
authored andcommitted
Introduce two new unit vector types for MVector
These new types are MPoint and MDirection
1 parent 282d581 commit 7336118

17 files changed

+604
-307
lines changed

client/src/graphics/frustum.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use common::Plane;
2-
use common::math::MVector;
2+
use common::math::MPoint;
33

44
#[derive(Debug, Copy, Clone)]
55
pub struct Frustum {
@@ -80,7 +80,7 @@ pub struct FrustumPlanes {
8080
}
8181

8282
impl FrustumPlanes {
83-
pub fn contain(&self, point: &MVector<f32>, radius: f32) -> bool {
83+
pub fn contain(&self, point: &MPoint<f32>, radius: f32) -> bool {
8484
for &plane in &[&self.left, &self.right, &self.down, &self.up] {
8585
if plane.distance_to(point) < -radius {
8686
return false;
@@ -101,29 +101,29 @@ mod tests {
101101
fn planes_sanity() {
102102
// 90 degree square
103103
let planes = Frustum::from_vfov(f32::consts::FRAC_PI_4, 1.0).planes();
104-
assert!(planes.contain(&MVector::origin(), 0.1));
104+
assert!(planes.contain(&MPoint::origin(), 0.1));
105105
assert!(planes.contain(
106-
&(MIsometry::translation_along(&-na::Vector3::z()) * MVector::origin()),
106+
&(MIsometry::translation_along(&-na::Vector3::z()) * MPoint::origin()),
107107
0.0
108108
));
109109
assert!(!planes.contain(
110-
&(MIsometry::translation_along(&na::Vector3::z()) * MVector::origin()),
110+
&(MIsometry::translation_along(&na::Vector3::z()) * MPoint::origin()),
111111
0.0
112112
));
113113
assert!(!planes.contain(
114-
&(MIsometry::translation_along(&na::Vector3::x()) * MVector::origin()),
114+
&(MIsometry::translation_along(&na::Vector3::x()) * MPoint::origin()),
115115
0.0
116116
));
117117
assert!(!planes.contain(
118-
&(MIsometry::translation_along(&na::Vector3::y()) * MVector::origin()),
118+
&(MIsometry::translation_along(&na::Vector3::y()) * MPoint::origin()),
119119
0.0
120120
));
121121
assert!(!planes.contain(
122-
&(MIsometry::translation_along(&-na::Vector3::x()) * MVector::origin()),
122+
&(MIsometry::translation_along(&-na::Vector3::x()) * MPoint::origin()),
123123
0.0
124124
));
125125
assert!(!planes.contain(
126-
&(MIsometry::translation_along(&-na::Vector3::y()) * MVector::origin()),
126+
&(MIsometry::translation_along(&-na::Vector3::y()) * MPoint::origin()),
127127
0.0
128128
));
129129
}

client/src/graphics/voxels/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ use crate::{
1616
loader::{Cleanup, LoadCtx, LoadFuture, Loadable, WorkQueue},
1717
};
1818
use common::{
19-
LruSlab, dodeca,
20-
dodeca::Vertex,
19+
LruSlab,
20+
dodeca::{self, Vertex},
2121
graph::NodeId,
2222
lru_slab::SlotId,
23-
math::{MIsometry, MVector},
23+
math::{MIsometry, MPoint},
2424
node::{Chunk, ChunkId, VoxelData},
2525
};
2626

@@ -127,7 +127,7 @@ impl Voxels {
127127
let mut workqueue_is_full = false;
128128
for &(node, ref node_transform) in nearby_nodes {
129129
let node_to_view = local_to_view * node_transform;
130-
let origin = node_to_view * MVector::origin();
130+
let origin = node_to_view * MPoint::origin();
131131
if !frustum_planes.contain(&origin, dodeca::BOUNDING_SPHERE_RADIUS) {
132132
// Don't bother generating or drawing chunks from nodes that are wholly outside the
133133
// frustum.

client/src/sim.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use common::{
1212
collision_math::Ray,
1313
graph::{Graph, NodeId},
1414
graph_ray_casting,
15-
math::{MIsometry, MVector},
15+
math::{MDirection, MIsometry, MPoint},
1616
node::{ChunkId, VoxelData, populate_fresh_nodes},
1717
proto::{
1818
self, BlockUpdate, Character, CharacterInput, CharacterState, Command, Component,
@@ -549,7 +549,7 @@ impl Sim {
549549
let ray_casing_result = graph_ray_casting::ray_cast(
550550
&self.graph,
551551
&view_position,
552-
&Ray::new(MVector::w(), -MVector::z()),
552+
&Ray::new(MPoint::w(), -MDirection::z()),
553553
self.cfg.character.block_reach,
554554
);
555555

common/src/character_controller/collision.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::{
66
collision_math::Ray,
77
graph::Graph,
88
graph_collision,
9-
math::{MIsometry, MVector},
9+
math::{MDirection, MIsometry, MPoint},
1010
proto::Position,
1111
};
1212

@@ -17,7 +17,6 @@ pub fn check_collision(
1717
relative_displacement: &na::Vector3<f32>,
1818
) -> CollisionCheckingResult {
1919
// Split relative_displacement into its norm and a unit vector
20-
let relative_displacement = relative_displacement.to_homogeneous();
2120
let displacement_sqr = relative_displacement.norm_squared();
2221
if displacement_sqr < 1e-16 {
2322
// Fallback for if the displacement vector isn't large enough to reliably be normalized.
@@ -26,11 +25,12 @@ pub fn check_collision(
2625
}
2726

2827
let displacement_norm = displacement_sqr.sqrt();
29-
let displacement_normalized = relative_displacement / displacement_norm;
28+
let displacement_normalized =
29+
na::UnitVector3::new_unchecked(relative_displacement / displacement_norm);
3030

3131
let ray = Ray::new(
32-
MVector::origin(),
33-
MVector::<f32>::from(displacement_normalized),
32+
MPoint::origin(),
33+
MDirection::<f32>::from(displacement_normalized),
3434
);
3535
let tanh_distance = displacement_norm.tanh();
3636

common/src/chunk_collision.rs

+35-32
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::{
22
collision_math::Ray,
3-
math,
4-
math::MVector,
3+
math::{MVector, PermuteXYZ},
54
node::{ChunkLayout, VoxelAABB, VoxelData},
65
voxel_math::Coords,
76
world::Material,
@@ -91,8 +90,9 @@ fn find_face_collision(
9190
for t in bounding_box.grid_planes(t_axis) {
9291
// Find a normal to the grid plane. Note that (t, 0, 0, x) is a normal of the plane whose closest point
9392
// to the origin is (x, 0, 0, t), and we use that fact here.
94-
let normal = math::tuv_to_xyz(t_axis, MVector::new(1.0, 0.0, 0.0, layout.grid_to_dual(t)))
95-
.normalized();
93+
let normal = MVector::new(1.0, 0.0, 0.0, layout.grid_to_dual(t))
94+
.tuv_to_xyz(t_axis)
95+
.normalized_direction();
9696

9797
let Some(new_tanh_distance) =
9898
ray.solve_sphere_plane_intersection(&normal, collider_radius.sinh())
@@ -121,7 +121,7 @@ fn find_face_collision(
121121
};
122122

123123
let ray_endpoint = ray.ray_point(new_tanh_distance);
124-
let contact_point = ray_endpoint - normal * ray_endpoint.mip(&normal);
124+
let contact_point = ray_endpoint - normal.as_ref() * ray_endpoint.mip(&normal);
125125

126126
// Compute the u and v-coordinates of the voxels at the contact point
127127
let Some(voxel_u) = layout.dual_to_voxel(contact_point[u_axis] / contact_point.w) else {
@@ -135,15 +135,15 @@ fn find_face_collision(
135135
if !voxel_is_solid(
136136
voxel_data,
137137
layout,
138-
math::tuv_to_xyz(t_axis, [voxel_t, voxel_u, voxel_v]),
138+
[voxel_t, voxel_u, voxel_v].tuv_to_xyz(t_axis),
139139
) {
140140
continue;
141141
}
142142

143143
// A collision was found. Update the hit.
144144
hit = Some(ChunkCastHit {
145145
tanh_distance: new_tanh_distance,
146-
normal,
146+
normal: normal.into(),
147147
});
148148
}
149149

@@ -168,14 +168,14 @@ fn find_edge_collision(
168168
// Loop through all grid lines overlapping the bounding box
169169
for (u, v) in bounding_box.grid_lines(u_axis, v_axis) {
170170
// Compute vectors Lorentz-orthogonal to the edge and to each other
171-
let edge_normal0 =
172-
math::tuv_to_xyz(t_axis, MVector::new(0.0, 1.0, 0.0, layout.grid_to_dual(u)))
173-
.normalized();
171+
let edge_normal0 = MVector::new(0.0, 1.0, 0.0, layout.grid_to_dual(u))
172+
.tuv_to_xyz(t_axis)
173+
.normalized_direction();
174174

175-
let edge_normal1 =
176-
math::tuv_to_xyz(t_axis, MVector::new(0.0, 0.0, 1.0, layout.grid_to_dual(v)));
177-
let edge_normal1 =
178-
(edge_normal1 - edge_normal0 * edge_normal0.mip(&edge_normal1)).normalized();
175+
let edge_normal1 = MVector::new(0.0, 0.0, 1.0, layout.grid_to_dual(v)).tuv_to_xyz(t_axis);
176+
let edge_normal1 = (*edge_normal1.as_ref()
177+
- *edge_normal0.as_ref() * edge_normal0.mip(&edge_normal1))
178+
.normalized_direction();
179179

180180
let Some(new_tanh_distance) = ray.solve_sphere_line_intersection(
181181
&edge_normal0,
@@ -192,8 +192,8 @@ fn find_edge_collision(
192192

193193
let ray_endpoint = ray.ray_point(new_tanh_distance);
194194
let contact_point = ray_endpoint
195-
- edge_normal0 * ray_endpoint.mip(&edge_normal0)
196-
- edge_normal1 * ray_endpoint.mip(&edge_normal1);
195+
- edge_normal0.as_ref() * ray_endpoint.mip(&edge_normal0)
196+
- edge_normal1.as_ref() * ray_endpoint.mip(&edge_normal1);
197197

198198
// Compute the t-coordinate of the voxels at the contact point
199199
let Some(voxel_t) = layout.dual_to_voxel(contact_point[t_axis] / contact_point.w) else {
@@ -206,7 +206,7 @@ fn find_edge_collision(
206206
!voxel_is_solid(
207207
voxel_data,
208208
layout,
209-
math::tuv_to_xyz(t_axis, [voxel_t, voxel_u, voxel_v]),
209+
[voxel_t, voxel_u, voxel_v].tuv_to_xyz(t_axis),
210210
)
211211
})
212212
}) {
@@ -248,17 +248,19 @@ fn find_vertex_collision(
248248
}
249249

250250
// Compute vectors Lorentz-orthogonal to the vertex and to each other
251-
let vertex_normal0 = MVector::new(1.0, 0.0, 0.0, layout.grid_to_dual(x)).normalized();
251+
let vertex_normal0 =
252+
MVector::new(1.0, 0.0, 0.0, layout.grid_to_dual(x)).normalized_direction();
252253

253254
let vertex_normal1 = MVector::new(0.0, 1.0, 0.0, layout.grid_to_dual(y));
254-
let vertex_normal1 =
255-
(vertex_normal1 - vertex_normal0 * vertex_normal0.mip(&vertex_normal1)).normalized();
255+
let vertex_normal1 = (vertex_normal1
256+
- vertex_normal0.as_ref() * vertex_normal0.mip(&vertex_normal1))
257+
.normalized_direction();
256258

257259
let vertex_normal2 = MVector::new(0.0, 0.0, 1.0, layout.grid_to_dual(z));
258260
let vertex_normal2 = (vertex_normal2
259-
- vertex_normal0 * vertex_normal0.mip(&vertex_normal2)
260-
- vertex_normal1 * vertex_normal1.mip(&vertex_normal2))
261-
.normalized();
261+
- vertex_normal0.as_ref() * vertex_normal0.mip(&vertex_normal2)
262+
- vertex_normal1.as_ref() * vertex_normal1.mip(&vertex_normal2))
263+
.normalized_direction();
262264

263265
let Some(new_tanh_distance) = ray.solve_sphere_point_intersection(
264266
&vertex_normal0,
@@ -281,13 +283,13 @@ fn find_vertex_collision(
281283
layout.grid_to_dual(z),
282284
1.0,
283285
)
284-
.normalized();
286+
.normalized_point();
285287

286288
// A collision was found. Update the hit.
287289
let ray_endpoint = ray.ray_point(new_tanh_distance);
288290
hit = Some(ChunkCastHit {
289291
tanh_distance: new_tanh_distance,
290-
normal: ray_endpoint - vertex_position,
292+
normal: ray_endpoint - vertex_position.as_ref(),
291293
});
292294
}
293295

@@ -355,20 +357,21 @@ mod tests {
355357
ray_start_grid_coords[2] / ctx.layout.dual_to_grid_factor(),
356358
1.0,
357359
)
358-
.normalized();
360+
.normalized_point();
359361

360362
let ray_end = MVector::new(
361363
ray_end_grid_coords[0] / ctx.layout.dual_to_grid_factor(),
362364
ray_end_grid_coords[1] / ctx.layout.dual_to_grid_factor(),
363365
ray_end_grid_coords[2] / ctx.layout.dual_to_grid_factor(),
364366
1.0,
365367
)
366-
.normalized();
368+
.normalized_point();
367369

368370
let ray = Ray::new(
369371
ray_start,
370-
((ray_end - ray_start) + ray_start * ray_start.mip(&(ray_end - ray_start)))
371-
.normalized(),
372+
((ray_end.as_ref() - ray_start.as_ref())
373+
+ ray_start.as_ref() * ray_start.mip(&(ray_end.as_ref() - ray_start.as_ref())))
374+
.normalized_direction(),
372375
);
373376

374377
let tanh_distance = (-ray_start.mip(&ray_end)).acosh();
@@ -511,12 +514,12 @@ mod tests {
511514
// The ray we care about is after its start point has moved to the contact point.
512515
let ray = MIsometry::translation(
513516
&ray.position,
514-
&ray.ray_point(hit.tanh_distance).normalized(),
517+
&ray.ray_point(hit.tanh_distance).normalized_point(),
515518
) * ray;
516519

517520
// Project normal to be perpendicular to the ray's position
518-
let corrected_normal =
519-
(hit.normal + ray.position * hit.normal.mip(&ray.position)).normalized();
521+
let corrected_normal = (hit.normal + ray.position.as_ref() * hit.normal.mip(&ray.position))
522+
.normalized_direction();
520523

521524
// Check that the normal and ray are pointing opposite directions
522525
assert!(corrected_normal.mip(&ray.direction) < 0.0);

common/src/chunk_ray_casting.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::{
22
collision_math::Ray,
3-
math,
4-
math::MVector,
3+
math::{MVector, PermuteXYZ},
54
node::{ChunkLayout, VoxelAABB, VoxelData},
65
voxel_math::{CoordAxis, CoordSign, Coords},
76
world::Material,
@@ -69,8 +68,9 @@ fn find_face_collision(
6968
for t in bounding_box.grid_planes(t_axis) {
7069
// Find a normal to the grid plane. Note that (t, 0, 0, x) is a normal of the plane whose closest point
7170
// to the origin is (x, 0, 0, t), and we use that fact here.
72-
let normal = math::tuv_to_xyz(t_axis, MVector::new(1.0, 0.0, 0.0, layout.grid_to_dual(t)))
73-
.normalized();
71+
let normal = MVector::new(1.0, 0.0, 0.0, layout.grid_to_dual(t))
72+
.tuv_to_xyz(t_axis)
73+
.normalized_direction();
7474

7575
let Some(new_tanh_distance) = ray.solve_point_plane_intersection(&normal) else {
7676
continue;
@@ -97,7 +97,7 @@ fn find_face_collision(
9797
};
9898

9999
let ray_endpoint = ray.ray_point(new_tanh_distance);
100-
let contact_point = ray_endpoint - normal * ray_endpoint.mip(&normal);
100+
let contact_point = ray_endpoint - normal.as_ref() * ray_endpoint.mip(&normal);
101101

102102
// Compute the u and v-coordinates of the voxels at the contact point
103103
let Some(voxel_u) = layout.dual_to_voxel(contact_point[u_axis] / contact_point.w) else {
@@ -111,15 +111,15 @@ fn find_face_collision(
111111
if !voxel_is_solid(
112112
voxel_data,
113113
layout,
114-
math::tuv_to_xyz(t_axis, [voxel_t, voxel_u, voxel_v]),
114+
[voxel_t, voxel_u, voxel_v].tuv_to_xyz(t_axis),
115115
) {
116116
continue;
117117
}
118118

119119
// A collision was found. Update the hit.
120120
hit = Some(ChunkCastHit {
121121
tanh_distance: new_tanh_distance,
122-
voxel_coords: Coords(math::tuv_to_xyz(t_axis, [voxel_t, voxel_u, voxel_v])),
122+
voxel_coords: Coords([voxel_t, voxel_u, voxel_v].tuv_to_xyz(t_axis)),
123123
face_axis: CoordAxis::try_from(t_axis).unwrap(),
124124
face_sign,
125125
});
@@ -186,20 +186,21 @@ mod tests {
186186
ray_start_grid_coords[2] / ctx.layout.dual_to_grid_factor(),
187187
1.0,
188188
)
189-
.normalized();
189+
.normalized_point();
190190

191191
let ray_end = MVector::new(
192192
ray_end_grid_coords[0] / ctx.layout.dual_to_grid_factor(),
193193
ray_end_grid_coords[1] / ctx.layout.dual_to_grid_factor(),
194194
ray_end_grid_coords[2] / ctx.layout.dual_to_grid_factor(),
195195
1.0,
196196
)
197-
.normalized();
197+
.normalized_point();
198198

199199
let ray = Ray::new(
200200
ray_start,
201-
((ray_end - ray_start) + ray_start * ray_start.mip(&(ray_end - ray_start)))
202-
.normalized(),
201+
((ray_end.as_ref() - ray_start.as_ref())
202+
+ ray_start.as_ref() * ray_start.mip(&(ray_end.as_ref() - ray_start.as_ref())))
203+
.normalized_direction(),
203204
);
204205

205206
let tanh_distance = (-(ray_start.mip(&ray_end))).acosh();

0 commit comments

Comments
 (0)