6

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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
JPNotADragon
  • 2,050
  • 2
  • 25
  • 31
  • Duplicate of [How do I implement a trait I don't own for a type I don't own](http://stackoverflow.com/q/25413201/155423)? – Shepmaster Oct 13 '16 at 17:57
  • @shepmaster: it's not really a duplicate, because I don't really want to implement that trait unless there's no better way. The link is informative though - thanks. – JPNotADragon Oct 13 '16 at 17:59

1 Answers1

8

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(),
    //                                      ^^^^^^^^^
};
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Lukas Kalbertodt
  • 79,749
  • 26
  • 255
  • 305
  • Thanks Lukas, that did the trick! I'm so new to Rust (started on Monday 3 days ago) that it didn't occur to me that there was nothing stopping me from defining and implementing my *own* trait. (Even so, I couldn't have come up with this on my own, too much left to learn still.) Out of curiosity, why did you stop doing stuff with cgmath and glium? – JPNotADragon Oct 13 '16 at 18:50
  • sorry @LukasKalbertodt forgot to correctly include your name in the above comment. – JPNotADragon Oct 13 '16 at 18:56
  • @JPNotADragon The name is not a problem, when you are commenting on my answer, since I get notified anyway ;-) Glad I could help. I did not stop working with `cgmath` or `glium`; sorry if my answer seem to imply it. I really like `cgmath` and think its design is terrific. While generally being pretty nice to use, `glium` has some design flaws, which tomaka itself acknowledges. A rewrite [is being considered](https://github.com/tomaka/glium2). But `glium` is still OK, so don't stop using it ;-) – Lukas Kalbertodt Oct 13 '16 at 19:05
  • Thanks! That's the answer I was hoping for :-) – JPNotADragon Oct 13 '16 at 19:09