Giter Club home page Giter Club logo

mint's Introduction

mint

Build Status Docs Crates.io

Math INteroperability Types

xkcd standard

This library provides standard mathematical types used in computer graphics. Its only purpose is to serve as a standard and interoperability language between various components of rust-gamedev ecosystem that happen to expose math-related types on their API. There are no operations defined for the types other than for the means of conversion from/into external types.
Serde support is available through the serde feature.

Types

This crate offers the following types:

Points

Matrices

Column Matrices

Row Matrices

Vectors

Quaternion

Euler Angles

MSRV

mint supports Rust 1.52.1 and newer. From time to time, mint may increase the minimum supported Rust version in a minor version bump in order to take advantage of new Rust features.

License

mint is available under the terms of the MIT license. See LICENSE or https://opensource.org/licenses/MIT for more information.

mint's People

Contributors

aloucks avatar burtonageo avatar eupn avatar frewsxcv avatar kvark avatar lpghatguy avatar mkhan45 avatar osspial avatar ralith avatar teoxoy avatar uriopass avatar vitvakatu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mint's Issues

From<Vector2> for (f32, f32) and friends

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.

Add iterop types for const-generic-dimensional types

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.

Consistent aliases

Current approach has RowMatrix aliasing with ColMatrix, yet there is Vector without Point. We should be consistent about having aliases.

  • either have them, so add Point2/3 types
  • or disallow them completely, so make a single Matrix type

I'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.

Generic numeric types?

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?

Default impl?

It would be convenient if mint::Vector2::default() worked (giving zeros) so my own structs could #[derive(Default)].

Bounding box types

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:

  1. There is no optimal representation that everyone agrees on. The pros/cons of each representation (min/max, center+extent, origin+size) depend on the actual usage. Arguably, the boxes shall be converted to a format for some math library before being processed anyway, so maybe it's not such a big a concern. I consider the "min/max" representation to be most canonical for having less types in it.
  2. One-dimensional boxes. Perhaps, just advising to use std::ops::Range is the way. Apparently, one can use it for floats.

cc @nical

Example?

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?

Design criteria

IMO, an interop layer should have the following qualities:

  • Lightweight
    The library should be small, compile quickly, and be easy to understand.
  • Zero-cost
    Adopting the library should not introduce additional run-time overhead compared to exposing internal types.
  • Un-opinionated
    No system to be interoperated with should feel like a second-class citizen. Reasonable differing conventions should have equal degrees of support.
  • Safe
    The library should prevent nonsensical or unintended operations.

The road to 1.0?

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"?

Quaternion handedness

Quaternions themselves do not encode handedness, but the associated methods do:

  • conversions to/from matrices
  • multiplication by a vector

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.

What about traits?

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.

Remove `uninitialized()` in favor of `MaybeUninit`?

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.

Conversion tests

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

Unique Conversion Trait

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!

Background

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.

MSRV

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.

Easy component type conversion, between mint types

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?

Type constructors

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.

Switch to const generics

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.

Implementations for Pod, Zeroable

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?

Implement `Add` and `Sub`

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!

Quaternion memory layout inconsistent with `into` (and similar libraries/specs)

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]).

Reproduce

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

Additional conversions

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?

Publish a new Version

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!()
}

Serialization

It would be nice to have Serde feature with Serialize/Deserialize implemented.

Bivectors and Rotors

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.

Source files distributed with executable bit set

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.

Restricting phantom types

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.

Euler angles

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

Colors support?

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...

#[repr(align)], GLSL and nightly

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.

Decomposed transformations

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.