I'm trying to integrate the cgmath
library into my first experiments with glium
, but I can't figure out how to pass my Matrix4
object to the draw()
call.
My uniforms
object is defined thus:
let uniforms = uniform! {
matrix: cgmath::Matrix4::from_scale(0.1)
};
and this is my draw
call:
target.draw(&vertex_buffer, &index_slice, &program, &uniforms, &Default::default())
.unwrap();
which fails to compile with the message
error[E0277]: the trait bound `cgmath::Matrix4<{float}>: glium::uniforms::AsUniformValue` is not satisfied
I'm a total beginner with Rust, but I do believe I cannot implement this trait myself, as both it and the Matrix4
type are in a crate separate from mine.
Is there really no better option than to manually convert the matrix into an array of arrays of floats?
I do believe I cannot implement this trait myself, as both it and the
Matrix4
type are in a crate separate from mine.
This is very true.
Is there really no better option than to manually convert the matrix into an array of arrays of floats?
Well, you don't have to do a lot manually.
First, it's useful to note that Matrix4<S>
implements Into<[[S; 4]; 4]>
(I can't link to that impl directly, so you have to use ctrl+f). That means that you can easily convert a Matrix4
into an array which is accepted by glium. Unfortunately, into()
only works when the compiler knows exactly what type to convert to. So here is a non-working and a working version:
// Not working, the macro accepts many types, so the compiler can't be sure
let uniforms = uniform! {
matrix: cgmath::Matrix4::from_scale(0.1).into()
};
// Works, because we excplicitly mention the type
let matrix: [[f64; 4]; 4] = cgmath::Matrix::from_scale(0.1).into();
let uniforms = uniform! {
matrix: matrix,
};
But this solution might be still too much to write. When I worked with cgmath
and glium
, I created a helper trait to reduce code size even more. This might not be the best solution, but it works and has no obvious downsides (AFAIK).
pub trait ToArr {
type Output;
fn to_arr(&self) -> Self::Output;
}
impl<T: BaseNum> ToArr for Matrix4<T> {
type Output = [[T; 4]; 4];
fn to_arr(&self) -> Self::Output {
(*self).into()
}
}
I hope this code explains itself. With this trait, you now only have to use
the trait near the draw()
call and then:
let uniforms = uniform! {
matrix: cgmath::Matrix4::from_scale(0.1).to_arr(),
// ^^^^^^^^^
};