Nalgebra 3D matrix transform_vector()

The AI gave me this test:

#[test]
fn matrix_translation() {
    let mut m = Matrix3d::identity();
    m.set_position(Vector3d(1.0, 2.0, 3.0, 0.0));

    assert_eq!(m.position(), Vector3d(1.0, 2.0, 3.0, 0.0));

    let v = Vector3d(0.0, 0.0, 0.0, 0.0);
    let t = m.transform_vector(v);
    assert_eq!(t, Vector3d::new(1.0, 2.0, 3.0, 0.0));
}

It's panicking at the assert_eq!(t, Vector3d::new(1.0, 2.0, 3.0, 0.0)); line:

thread 'geom::matrix3d::tests::matrix_translation' (10124) panicked at crates\whack\src\geom\matrix3d.rs:828:9:
assertion `left == right` failed
  left: (0, 0, 0)
 right: (1, 2, 3)

Here are the relevant parts of Matrix3d:

// row-major order; mostly always built by nalgebra
pub struct Matrix3d(pub [f64; 16]);

impl Matrix3d {
    pub fn identity() -> Self {
        Self([
            1.0, 0.0, 0.0, 0.0,
            0.0, 1.0, 0.0, 0.0,
            0.0, 0.0, 1.0, 0.0,
            0.0, 0.0, 0.0, 1.0,
        ])
    }

    pub fn position(&self) -> Vector3d {
        Vector3d(self.0[12], self.0[13], self.0[14], 0.)
    }

    pub fn set_position(&mut self, pos: Vector3d) {
        self.0[12] = pos.0;
        self.0[13] = pos.1;
        self.0[14] = pos.2;
    }

    pub fn transform_vector(&self, v: Vector3d) -> Vector3d {
        Vector3d::from(self.to_na().transform_vector(&v.to_na_3()))
    }

    /// Returns the `nagelbra` version of this matrix.
    pub fn to_na(&self) -> nalgebra::Matrix4<f64> {
        nalgebra::Matrix4::from_row_slice(&self.0)
    }
}

Is it correct or wrong? Or is nalgebra not aware this is a 3D matrix (4x4)?

From Adobe documentation:

Note Vector3d has an optional component w, to comply mostly with the Adobe Display List.

The origin in homogeneous coordinates in 3d is (0,0,0,1).

1 Like

So (0, 0, 0) is the expected result? I'd have to update the RustDoc comment then...

Vectors (w=0) are not affected by translation by definition. Only points (w=1) are.

Incidentally, I’ve been writing my MSc thesis on this distinction, among other things, and how linear and affine objects (vectors and points) should definitely be distinct types, because homogeneous coordinates are all kinds of confusing and error-prone. (nalgebra does distinguish them, mind.)

1 Like

Oh, this is a bit confusing :face_with_spiral_eyes: According to Flash Player the w component is optional data and may be used for rotation...

I've tried using transform_point instead, but it just doesn't accept a four-sized na::Point:

/// Uses the transformation matrix to transform a `Vector3d` object
/// from one space coordinate to another.
pub fn transform_vector(&self, v: Vector3d) -> Vector3d {
    self.to_na().transform_point(&v.to_na_point_4()).into()
}

I've also tried with transform_vector() a 4-sized vector and same issue!

Here is the playground

Your problem is on line 689.

Instead of using from_row_slice, change it to:

        nalgebra::Matrix4::from_column_slice(&self.0)
1 Like

Thanks. I've decided to just reuse OpenFL's formulas, because the AI probably gave me wrong implementations of the other stuff, so I'll be able to cut the nalgebra dependency off.

Just can't rely much on AI X_X

My thoughts exactly.

FWIW, after looking at your code, I thought you have way too much code dealing with elementary operations. Most of that stuff is already implemented on nalgebra. What I mean is that, basically, all you need is matrix-vector multiplication. My advice would be to stick with nalgebra, work all the way in homogenous coordinates using nalgebra, and have a couple of functions to transform the vector to/from Cartesian coordinates.

2 Likes

I decided to keep nalgebra as a dependency since I already use it on Vector3d a bit. Guess it won't be much of an overload?

I've one question: why are we going from row-major to column-major? I thought my raw_data (matrix3d.0: [f64; 16]) was consisting of the row-major order...

Also wondering if this is correct:

impl From<nalgebra::Matrix4<f64>> for Matrix3d {
    fn from(value: nalgebra::Matrix4<f64>) -> Self {
        // `as_slice` gives you a &[f64] in *row-major order*
        Self(value.as_slice().try_into().unwrap())
    }
}

When you set/get the position in/from the matrix (lines 274-282), you use the indices 12, 13, 14. That assumes your slice is in column-major order (i.e., the last 4 indices 12-15, correspond to the last column).

The Matrix struct in nalgebra is in column-major order. What makes you think that as_slice returns it in row-major? Is that comment in your code AI-generated? The nalgebra docs say it is column-by-columns.

1 Like

Yes, the AI generated that code piece.

Uh, I also somehow got some wrong indicator of what order I was using when sending AI prompts. But you've cleared it out...

I'm glad the problem was resolved. I can see from your project that you want to learn rust by trying to build a new algebra library. and learn from old library at the same time :thinking:

1 Like

I'm already experienced with high-level Rust, but I'm not the nice with the math :confused:

I might announce the project later, but basically I've been trying to do it before and gave up (agera). It's an engine that mimmicks the Flash DisplayList and React. Currently there are cross-platform timers (tickers and easy timers), file system APIs (similiar to Adobe AIR's flash.filesystem.File and flash.net.FileReference, but mostly asynchronous due to web using HTTP requests for app: and Origin Private File System web APIs).

I want to name it something else, but for now not sure if I should announce it...

The user interface will be built to be similiar to DOM, except I believe it should be faster than that DOM in HTML5.


This Agera repository isn't up to date with the changes I made, but... File system is a way more elaborated now and I won't use the struct inheritage emulator anymore; I'll make a hardcoded closed DisplayList and UiComponent DOM, and allow the user to implement reactive user interfaces upon the DOM.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.