Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make nalgebra easier to use #727

Closed
ottworks opened this issue Apr 23, 2020 · 3 comments
Closed

Make nalgebra easier to use #727

ottworks opened this issue Apr 23, 2020 · 3 comments

Comments

@ottworks
Copy link

Let's say I want to move a kinematic body in nphysics. RigidBody has a set_position function, sounds simple enough.

fn move_body(body: &mut nphysics3d::object::rigid_body::RigidBody<f32>, move_dir: Vector3<f32>, dt: f32) {
    body.set_position(body.position() + move_dir * dt);
}

error[E0369]: cannot add `na::Matrix<f32, na::U3, na::U1, na::ArrayStorage<f32, na::U3, na::U1>>` to `&na::Isometry<f32, na::U3, na::Unit<na::Quaternion<f32>>>
Okay... What's an isometry? Oh I see, it represents translation and rotation. It's got some functions to transform points... ah! Append translation! That takes a Translation3... which I can convert a vector into. Oh, it's mut only, so I'll have to .to_owned...

fn move_body(body: &mut nphysics3d::object::rigid_body::RigidBody<f32>, move_dir: Vector3<f32>, dt: f32) {
    let mut new_pos = body.position().to_owned();
    new_pos.append_translation_mut(&Translation3::from(move_dir * dt));
    body.set_position(new_pos);
}

There! Perfectly concise, readable code.

nalgebra is hard to use. Every user-facing type like Vector3 is actually something else behind six different type aliases and expands to garbage like na::Matrix<f32, na::U3, na::U1, na::ArrayStorage<f32, na::U3, na::U1>> in errors. For every line of code I write, I have to open two new tabs of documentation. For starters, I'd like to see more convenience functions and operators so that I don't have to do a billion conversions to get two things to interact with each other.

@Andlon
Copy link
Sponsor Collaborator

Andlon commented Apr 23, 2020

For starters, I'd like to see more convenience functions and operators so that I don't have to do a billion conversions to get two things to interact with each other.

nalgebra does actually have quite a lot of convenience functions, but it seems as if you've unfortunately landed in a situation in which none of these actually help you. I'm not sure if it's particularly relevant for you, but have you looked at nalgebra-glm? It's designed as a kind of "easy-mode" for computer graphics applications.

Perhaps a method like Isometry::translated(&self, translation: &VectorN<T, D>) would be nice to have (and similarly rotated). Then you could write

body.set_position(body.position().translated(&(move_dir * dt)));

Edit: See @sebcrozet's example below for what you can do with nalgebra right now.

As for the general complexity of nalgebra, this is unfortunately at the moment absolutely necessary. It is what allows nalgebra to work seamlessly across dimensions, and is crucial to enable applications which need both small computer graphics primitives and more general linear algebra operations. Without this genericity, I'd still be writing C++.

An unfortunate contributor to the complexity of nalgebra is the lack of proper support for const generics, which would mean that the compiler can parametrize over constant quantities like usize at compile time. nalgebra works around this by using the excellent typenum crate, but at the end of the day it is a bit of a type-level hack that unfortunately adds a lot of complexity. Hopefully, when Rust finally gets proper const generics support, the generic API of nalgebra can be made simpler.

@sebcrozet
Copy link
Member

First, here is the most concise way of doing what you are trying to do:

body.set_position(Translation3::from(move_dir * dt) * body.position());

The Isometry3 + Vector is like adding apples and oranges; this operation makes no mathematical sense. This is similar to adding f32 + usize which does not work in Rust because it makes no sense. Transformations are supposed to be composed by multiplication. This is mentioned in the point and transformations section of the user guide:

Transformations can be composed (by multiplication) even if they do not have the same type. The type of the composition result is the most general transformation of both. For example, multiplying a Projective3 (inversible transformation) with a Similarity3 yields a Projective3 because all similarities are inversible. An exception is the product of any pure rotation by a pure translation: none is more general than the other so the result is an Isometry2/3 which is the most specific transformation enough to represent this composition.

Though I agree this may not be clear enough, and would deserve some examples.


There are a few reasons why nalgebra is not easy to use when you start with this crate. First nalgebra has a lot of features designed to be used in both generic and non-generic contexts. It covers most feature you would need from simple 2D/3D math, to complex operations like matrix decomposition. This results in a few issues:

  • The rustdoc-generated documentation is difficult to browse. This would be significantly easier if that rustdoc bug was fixed (for the documentation of type aliases). Also if rustdoc supported sections we could group methods by theme, but that's not possible.
  • Error messages take some time to get used to. As @Andlon mentioned, they will become much better when const-generics land.

The thing is that nalgebra is designed to get better when rustc and rustdoc will get better. In the mean time, the learning curve is still quite steep and we try to ease this with the user guide and doc-tests. The problem you are facing clearly shows that the user-guide deserves more examples, and perhaps we should add some examples at the top of the rustdoc documentation pages.

@ottworks
Copy link
Author

ottworks commented Apr 23, 2020

Thanks, I'll check out nalgebra-glm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants