kvark / mint Goto Github PK
View Code? Open in Web Editor NEWMath Interoperability Types
License: MIT License
Math Interoperability Types
License: MIT License
Hiya!
The recent changes in the last commit allowed for some type simplification as a library maker.
// this COMPILES ON MASTER right now, but NOT on `0.5.6`.
fn test<T>(input: &mut T)
where
T: Copy + Into<MintVec3> + From<MintVec3>,
{
let as_mint = (*input).into();
let mut as_vec3: [f32; 3] = as_mint.into();
let changed = mutate_vec3(&mut as_vec3);
if changed {
let as_mint: MintVec3 = as_vec3.into();
*input = as_mint.into();
}
}
// this compiles on both, but is ugly
fn test3<T>(input: &mut T)
where
T: Copy + Into<MintVec3>,
MintVec3: Into<T> + Into<[f32; 3]>,
{
let as_mint = (*input).into();
let mut as_vec3: [f32; 3] = as_mint.into();
let changed = mutate_vec3(&mut as_vec3);
if changed {
let as_mint: MintVec3 = as_vec3.into();
*input = as_mint.into();
}
}
fn mutate_vec3(input: &mut [f32; 3]) -> bool {
todo!()
}
Hello!
I'm working on a library called tween
and I cant use Mint if it doesn't implement Add
and Sub
. I know that Mint isn't a math library, and i suspect that add and sub aren't implemented to make it very clear that no operations are performed by mint, but these are simple, basic operations, which have obvious implementations.
In my library, I need certain T to impl Add
and Sub
. I could instead use methods add
and sub
, but...welll...there's a reason we don't do that in general in Rust! It makes the code extremely unreadable.
Right now, I support 4 math libraries. I'd like to, basically, not, and only support mint and do conversions for users instead.
Thank you!
Current approach has RowMatrix
aliasing with ColMatrix
, yet there is Vector
without Point
. We should be consistent about having aliases.
Point2/3
typesMatrix
typeI'm in favour of no aliases rule. It's not clear what to do with EulerAngles
in this case. We can either turn it into a tuple or remove the alias entirely.
It'd be interesting to see if we can have auto-conversions from mint-0.3 to mint-0.4, for example. That would greatly ease the cost of updating the version.
Would allow us to use m[3][2]
instead of current m.z.y
.
Possibly behind deref
feature since it's unsafe code?
cc @Ralith
It would be nice to have Serde feature with Serialize/Deserialize implemented.
Since the const generics mvp was just stabilized, a large number of const generics linear algebra packages are hitting stable at roughly the same time. A standard to make them all compatible with each other would be great to have.
So a possible set of types would be n-dimensional points, n dimensional vectors, m x n dimensional row matrices, and m x n dimensional column matrices.
Of course, there is also the possibility of taking the existing types with hardcoded dimensions and turning them into aliases for the generic-dimension types specialized at various dimensions, though that would be a separate issue.
There is not much we can test in this library, but at least we can make sure that all of the From/Into
fixed-point arrays (and between, e.g. RowMatrix
and ColumnMatrix
) are bijective, similar to how euclid <-> mint testing is done in servo/euclid#205
Writing down mint::Vector3::new(x,y,z)
can be often replaced with [x,y,z].into()
, but the former is more familiar to many and somewhat clearer. Problem with that is - introducing methods, where currently there is none. We may decide to only allow simple constructors, like new
.
So these things are super useful for any computer graphics math...
Is it in the scope of mint to add these implementations perhaps under and optional feature flag?
This would save the user from having to do extra wrapping.
Is it possible? Is it worth it?
There are some libraries that use tuples like this. E.g. glyph_brush's Section::with_bounds takes a Into<(f32, f32)>. So I need to match or something if I want to pass a Vector2. (I actually do this many times in my code). Implementing this trait and related traits would probably make many peoples code a bit less verbose.
I wouldn't mind to contribute this.
This issue probably implies both From<VectorN<T>> for (T1, ..., TN)
as well as From<(T1, ..., TN)> for VectorN<T>
. The same for Point.
Many files in src and in the root directory published in 0.5.2 have the executable bit set. At Debian, we put the source files into a package, and the executable bit propagates into the package. Files having the executable bit set is strongly discouraged by Linux distributions due to security reasons if they aren't intended to get executed, so I got a lintian warning when attempting to package mint 0.5.2 for Debian.
Basically, there's some points where uninitialized!()
gets used when we are implementing conversions that could be turned into MaybeUninit
. This looks pretty straightforward. The real question is, since this only got stabilized in rustc 1.36, is it desirable to require that as a minimum version for Mint? Not sure if that counts as a semver breaking change.
Travis is no longer used here.
I think people (including me) sometimes want to convert f64
types and f32
types or such component type conversion.
For example, downgrading Point3<f64>
to Point3<f32>
.
These conversions cannot be written using only From
and Into
trait (because of coherence), so usually it is done by .map()
function.
(See Option::map
and Result::map
for example.)
I'm not sure how this should be implemented in this crate, .map()
method, Map
trait, or something else...
Are these component type conversion in scope of this crate?
It would be nice to introduce defmt as dependency (it will bump MSRV to 1.65 I believe) and add the derives behind a feature.
I see there hasn't been much development in the crate but there are some opened PRs and I think this would a good addition as a feature especially since embedded-hal 1.0 crate was recently released and there are a few driver crates that use mint
like the bno055
one.
Does numeric wrappers like normalized value (always in 0..1 range), only negative, only positive, non-zero, arbitrary range are in scope of this crate?
I think, it should be possible to represent all types of this library as const generics already.
This would allow vectors, points and matrices (etc.) of higher dimensions as well.
The currently existing types can still exist by using type aliases, so this isn't even a breaking change.
The scalar component should be defined after the vector component or the implementation of into
needs to be changed.
Both glm and the GLTF spec define a quaternion with the scalar component after the vector component (i.e [x, y, z, w]
).
use mint::{Quaternion, Vector3};
fn main() {
let q = Quaternion {
s: 1.0,
v: Vector3::from([0.0, 0.0, 0.0]),
};
let a: &[_; 4] = &q.into();
let b: &[_; 4] = q.as_ref();
assert_eq!(a, b);
}
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `[0.0, 0.0, 0.0, 1.0]`,
right: `[1.0, 0.0, 0.0, 0.0]`', src\main.rs:9:5
It would be great to have the decomposed transforms standardized. This is a transform representation having separate scale/rotation/position, as opposed to Matrix
where it's all mixed up.
Hello,
As this is cg-related library, one would expect its types to have certain alignment constraints. E.g. in GLSL, vec3 and vec4 are 16 bytes aligned, dvec3 and dvec4 are 32 bytes aligned and so on. Unfortunately #[repr(align)] attribute is not yet present (rust-lang/rust#33626) in stable, I think it would be nice to have alignment enabled on nightly or something.
Note that in case of library such as, say, Vulkano, even though vertex objects do not need to have fields aligned by user in them, it is not always that user works with pure vertex objects (say, in case of objects shared between compute and graphics pipelines). As of now, user would need to align and pad structure by themselves or use types padded by Vulkano's shader deriver. Using #[repr(align)] on nightly, would let user use mint for vec3 etc types without having to do extra work of padding, on nightly.
It would be nice to have a method for casting between the generic number types (e.g. T
in Point2<T>
).
Maybe something similiar to winit::dpi::PhysicalPosition::cast
.
I've had an exciting read of http://marctenbosch.com/quaternions/, and one of the basis points they are making is that normals (like other bivectors) aren't in the same space as vectors. This is precisely the semantics we are trying to express here in mint's type system, so it would be great to expose the bi-vector and rotor types.
As @Ralith pointed out, the current implementation uses RowMatrix2x3
, RowMatrix3x4
, incorrectly.ColumnMatrix3x2
, and ColumnMatrix4x3
Note: this will be a breaking change.
IMO, an interop layer should have the following qualities:
There's been discussions about providing standard data structures for common math types, but the interop question can also be addressed through traits. What would be the pros and cons of mint defining traits instead of data structures?
the kind of traits I am thinking about could be like:
pub trait Vector<T> {
pub fn dot(&self, other: &Self) -> T;
// ... whatever else is common enough and deserves to be here
}
pub trait Vector3<T> : Vector<T> {
fn x(&self) -> T;
fn y(&self) -> T;
fn z(&self) -> T;
// ... whatever else is common enough and deserves to be here
}
pub trait Point3<T> {
fn x(&self) -> T;
fn y(&self) -> T;
fn z(&self) -> T;
// ... whatever else is common enough and deserves to be here
}
pub trait Transform<From, To> {
fn transform(&self, a: &From) -> To;
// etc..
}
// more traits, etc.
Or could look very different, I don't know. I just want to get the discussion started. I have a feeling that I would prefer standard traits over standard data structures, probably because adding new data structures next to the ones I am already happily using feels redundant and cumbersome, but I'd need to explore this more to have an idea of how useful that would be.
There seem to be quite a bit of chaos in the way Euler angles are defined. There are intrinsic (also called Tait-Bryan) and extrinsic (also called Proper Euler) types, and the axis following in any direction. There is a property that intrinsic (ABC) = extrinsic (CBA).
Wiki lists the established conventions to be extrinsic ZXZ and intrinsic ZYX. At the same time, ThreeJS (and cgmath-rs, for that matter) use intrinsic XYZ.
Proposal: have the order set explicitly in the name, e.g.: TaitBryanXYZ
, TaitBryanZYX
, ProperEulerZXZ
, etc.
At the very least, there is no ambiguity/assumptions baked into that. Ideally, we'd want the relationship between intrinsic order and extrinsic order to also be encoded into the type system (that ABC=CBA thing), but I don't see the way to get it, yet.
See also - mrdoob/three.js#10485
I PR'd the IntoMint
trait in #68 and promised I would follow-up with PRs to math libraries to update their usage of mint. Even if I don't finish that work for all libraries, it'd be nice to have a tracking issue to see how we're doing.
While implementing mint
support for gltf
crate I faced the following problem:
/// 4x4 column-major transformation matrix.
- pub fn matrix(&self) -> [f32; 16] {
- self.json.matrix
+ pub fn matrix(&self) -> ColumnMatrix4<f32> {
+ let m = self.json.matrix;
+ let vec = [
+ [m[0], m[1], m[2], m[3]],
+ [m[4], m[5], m[6], m[7]],
+ [m[8], m[9], m[10], m[11]],
+ [m[12], m[13], m[14], m[15]],
+ ];
+ vec.into()
}
It's too boilerplate.
I suggest new conversions for mint
matrices:
[T; 16]
-> ColumnMatrix4<T>
, RowMatrix4<T>
[T; 9]
-> ColumnMatrix3<T>
, RowMatrix3<T>
What's your opinion?
It would be convenient if mint::Vector2::default()
worked (giving zeros) so my own structs could #[derive(Default)]
.
Is colors out of scope, or can be supported?
I'm writing 3D model loader and want to return color data, but I think neither Point{3,4}
nor Vector{3,4}
is appropriate.
I'm happy if mint supports color types, because color is very important for computer graphics (and gamedev).
However, I'm not sure they are "mathematical" type...
Quaternions themselves do not encode handedness, but the associated methods do:
Perhaps, it would make sense to introduce LeftQuaternion
type that is associated with left-handed matrix? E.g. a matrix to quaternion conversion would then return either Quaternion
or LeftQuaternion
depending on the basis of the matrix.
Math libraries (optional dependency):
Higher level libs:
Just wanted to foster some conversation, since mint
is going into the public-facing API of the next version of ggez
. The goal is to prevent problems such as this one, but with the possibility of a mint
0.6 in the works this really just moves the problem of version dependency from one place to another. mint
isn't going to move as fast or change as much as nalgebra
is, so really this is a problem of perception more than anything else, but having a 1.0 version might still be nice.
Any thoughts on what might need to be done for this? Or are we still at the stage of "have people use it and see if there are API problems that need fixing"?
It feels a little bit weird that we can put any type in place of the second parameter of LeftQuaternion
or EulerAngles
. Perhaps, this is not a problem on mint
side, since you can always abuse it if you really want to.
At risk of sounding like an idiot, how does one actually use mint in their code?
Can someone whip up like a tiny example for me, maybe whack it in the README?
It would be nice for mint to provide a trait using an associated type to define a surjective conversion function. This would help crates distinguish normal conversions with From
/Into
and establish an equivalence relationship between mint types and individual math crates.
The trait I have in mind looks something like this:
trait IntoMint {
type MintType;
fn into_mint(&self) -> Self::MintType;
}
You've mentioned before that mint should not have traits. I think I have a compelling use case and I'm not sure how else I can solve it!
I am working on a library named Crevice, which generates std140 versions of structs that are safe to treat as byte slices and upload to the GPU. It depends heavily on mint as the common vector type library and bases all of its conversions on it.
Usage is something like this:
#[derive(AsStd140)]
struct PointLight {
position: mint::Vector3<f32>,
color: mint::Vector3<f32>,
brightness: f32,
}
let light = PointLight {
position: [1.0, 2.0, 3.0].into(),
color: [1.0, 1.0, 1.0].into(),
brightness: 3.0,
};
upload_data_to_gpu(light.as_std140().as_bytes());
One awkward portion of the API is that users need to define their structs using Mint types, Crevice's format-specific types (std140::Vec2
, std430::Mat2
, etc), or plain arrays. Crevice effectively generates a companion struct that looks like this:
struct PointLightStd140 {
position: <mint::Vector3<f32> as AsStd140>::Std140Type,
_pad0: [u8; 4],
color: <mint::Vector3<f32> as AsStd140>::Std140Type,
brightness: <f32 as AsStd140>::Std140Type,
}
At proc macro time, it isn't possible for Crevice to tell which mint type should be converted through for a user's type. Ideally, users would be able to write this definition:
struct PointLight {
position: cgmath::Vector3<f32>,
color: cgmath::Vector3<f32>,
brightness: f32,
}
This could work if Crevice could write this blanket impl for AsStd140
:
impl<T> AsStd140 for T where T: IntoMint {
type Std140Type = <<T as IntoMint>::MintType as AsStd140>::Std140Type;
}
Crevice would need to be changed so that this is the only blanket impl for the trait, but I think that would be okay.
Concepts like an axis-aligned bounding box are well understood and used widely. We may consider trying to standardize the simplest forms (Range, Box2, Box3).
Issues:
std::ops::Range
is the way. Apparently, one can use it for floats.cc @nical
I noticed that CI runs only on Rust stable and nightly.
What should mint's MSRV be?
As part of #69 for glam, it appears that on Rust 1.51.0, the IntoMint
trait's definition triggers a funny compiler error: https://github.com/bitshifter/glam-rs/runs/3985545407?check_suite_focus=true
1.51.0 is around 7 months old, so it would be reasonable to expect a newer Rust compiler, but I think it would be good to set that in stone by checking for it in CI.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.