Skip to content

Commit 7fa2acf

Browse files
committed
Math required to implement MeshGroup.
Three parts: - Testing whether a point is in a triangle. - Efficient (but not guaranteed correct) testing of a point is in which triangle among those in a given mesh, with a bitmask constructed for the mesh. - Given parent mesh and parent deformation, deform child mesh. Essentially letting one parent triangle drag a child vertex that is contained in it, and this drag can be chacterized by an inverse matrix, which can be reused for efficiency. Intensive test for bitmask included (with a .png depicting the base test case), testing that bitmask yields correct test results for points with the whole test space transforming. However, as mentioned, this bitmask method is not guaranteed to be correct, thus it is hard to define a "good enough" test case. It is easy to construct counterexamples. An experimental attempt on dynamic bitmask step size is commented out cause test suites do not like it. A step size of `1` should be usable in actual rendering anyways.
1 parent 2c05a25 commit 7fa2acf

File tree

4 files changed

+393
-1
lines changed

4 files changed

+393
-1
lines changed

inox2d/src/math.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ pub mod deform;
33
pub mod interp;
44
pub mod matrix;
55
pub mod transform;
6+
pub(crate) mod triangle;

inox2d/src/math/bit_mask_test.png

12.7 KB
Loading

inox2d/src/math/deform.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use glam::Vec2;
1+
use glam::{Mat2, Vec2};
22

33
/// Different kinds of deform.
44
// TODO: Meshgroup.
@@ -22,3 +22,46 @@ pub(crate) fn linear_combine<'deforms>(direct_deforms: impl Iterator<Item = &'de
2222
.for_each(|(sum, addition)| *sum += *addition);
2323
}
2424
}
25+
26+
/// Input: two basis vectors `b0` and `b1`.
27+
///
28+
/// If the returned matrix is to be applied on a Vec2 V and X is obtained,
29+
/// then `X.x * b0 + X.y * b1 = V`.
30+
///
31+
/// Panics if either basis is zero or they are not independent of each other.
32+
pub fn vector_decompose_matrix(b0: Vec2, b1: Vec2) -> Mat2 {
33+
// B X = V where:
34+
// B: [ b0.x b1.x
35+
// b0.y b1.y ]
36+
// X: [ x
37+
// y ]
38+
// V: [ v.x
39+
// v.y ]
40+
// thus X = B^-1 V
41+
let mat = Mat2::from_cols(b0, b1).inverse();
42+
debug_assert_ne!(mat.determinant(), 0.0, "Provided two basis do not span the 2D plane.");
43+
mat
44+
}
45+
46+
/// Provide a parent triangle and its deforms by 3 points,
47+
/// calculate how far should the provided points be moved by the triangle's deform.
48+
///
49+
/// For optimization, the "decompose_matrix" of parent should be provided, see `vector_decompose_matrix()`.
50+
/// It is assumed that `parent[0]` is taken as the origin,
51+
/// `parent[1] - parent[0]` is the first basis vector, and `parent[2] - parent[0]` the second.
52+
#[inline]
53+
pub fn deform_by_parent_triangle<'a>(
54+
decompose_matrix: &'a Mat2,
55+
parent_p0: Vec2,
56+
parent_deforms: &'a [Vec2; 3],
57+
points: impl Iterator<Item = &'a Vec2> + 'a,
58+
) -> impl Iterator<Item = Vec2> + 'a {
59+
let basis_0_deform = parent_deforms[1] - parent_deforms[0];
60+
let basis_1_deform = parent_deforms[2] - parent_deforms[0];
61+
62+
points.map(move |p| {
63+
let decomposed_coeffs = *decompose_matrix * (*p - parent_p0);
64+
// deform by parent[0] + deform by basis change
65+
parent_deforms[0] + decomposed_coeffs.x * basis_0_deform + decomposed_coeffs.y * basis_1_deform
66+
})
67+
}

0 commit comments

Comments
 (0)