Nalgebra FFI guide?


#1

Hi,
I am trying to use nalgebra in a mixed project where some parts are written in c/c++, and I am struggling with questions like:
- How do I get a UnitQuaternion from [f32; 4]? (assuming the latter is known to be of unit length)
- How do I convert [f32; 16] to IsometryMatrix3? (again, assuming it is a valid isometry transform)
- What about the reverse of these?
- Is there an equivalent of Eigen::Map?
- Which types are bit-compatible with Eigen’s? And to which types? (I am guessing that Matrix4<f32> ~ Eigen::Matrix4f, but what about IsometryMatrix3<f32>? Is the same as Eigen::Isometry3f).
… and so on.

Are there any resources out there on nalgebra + FFI?


#2

Hi,

There are no resources on nalgebra + FFI since I did not consider this until now. I can answer to some o the questions though:

How do I get a UnitQuaternion from [f32; 4]? (assuming the latter is known to be of unit length)

Constructing an UnitQuaternion from an array amounts to first converting the array to a 4D vector which can itself be converted to a quaternion:

let vector = Vector4::from(array);
let quaternion = Quaternion::from_vector(vector);
let unit_quaternion = UnitQuaternion::new_unchecked(quaternion);

How do I convert [f32; 16] to IsometryMatrix3? (again, assuming it is a valid isometry transform)

In nalgebra, matrices can be constructed from and converted to arrays-of-arrays.
Thus constructing an IsometryMatrix3 from a [[f32; 4]; 4] can be achieved first by converting the array into a Matrix4 which can itself be converted to an IsometryMatrix3:

let matrix = Matrix4::from(array);
let iso_mat: IsometryMatrix3<f32> = na::convert_unchecked(matrix);

What about the reverse of these?

There is currently no way to convert a unit quaternion to an array with only one function. The best way would be to retrieve its vector representation which can be converted to an array:

let vector = *unit_quaternion.unwrap().as_vector();
let array: [f32; 4] = vector.into();

To convert an IsometryMatrix3 to a [[f32; 4]; 4], it is first necessary to convert it in homogeneous coordinates (a Matrix4) and then into an array:

let matrix = isometry_matrix.to_homogeneous();
let array: [[f32; 4]; 4] = matrix.into();

Is there an equivalent of Eigen::Map?

The closest thing would be the slice type aliases MatrixSlice*, VectorSlice*, DMatrixSlice, DVectorSlice, which can wrap an array so it is interpreted as a vector or matrix, taking strides into account.


Which types are bit-compatible with Eigen’s? And to which types? (I am guessing that Matrix4 ~ Eigen::Matrix4f, but what about IsometryMatrix3? Is the same as Eigen::Isometry3f).

Matrices and vectors are both compatible with Eigen since nalgebra follows a column-major storage convention as well. Quaternions are also compatible since all components are stored in the same order (the vector part first, and the angle part at the last position). For IsometryMatrix3, I am not 100% sure but it should match with the layout of the Eigen::Isometry3f that relies on the AffineCompact representation of an Eigen Transformation.


Writing this answer, I realize the conversion to and from arrays is not quite obvious. I think all those conversion should be available with only one function call. I’ve created an issue to track this.


#3

Thanks!

That’d be nice!
But please consider also adding a section on FFI (and perhaps on conversions in general) to the User Guide. Figuring out from RustDoc which of the from’s, into’s, new_from’s or convert’s one needs to use is not easy, so adding new functions might not help as much as you hope.