0

I decided to learn a bit about matrices and 3D cameras and made some educational project for myself, to understand how it works. Swift and SwiftUI because I'm a bit familiar with. But question is more math-general-oriented.

Why x-rotation looks wired? looks strange

y-axis and z-axis looks great btw.

Here are my matrices for rotation and camera:

extension Matrix {
    static func rotateX(_ angle: CGFloat) -> Matrix 
    {
        Matrix([
            [ 1, 0, 0, 0],
            [ 0, cos(angle), sin(angle), 0],
            [ 0, sin(angle), cos(angle), 0],
            [ 0, 0, 0, 1 ]
        ])
    }
    
    static func rotateY(_ angle: CGFloat) -> Matrix 
    {
        Matrix([
            [ cos(angle), 0,sin(angle), 0],
            [ 0, 1, 0, 0],
            [ -sin(angle), 0, cos(angle), 0],
            [ 0, 0, 0, 1 ],
        ])
    }
    
    static func rotateZ(_ angle: CGFloat) -> Matrix 
    {
        Matrix([
            [ cos(angle), sin(angle), 0, 0],
            [-sin(angle), cos(angle), 0, 0],
            [ 0, 0, 1, 0],
            [ 0, 0, 0, 1 ]
        ])
    }
    
    static func rotate(_ p: Point3D) -> Matrix {
        Matrix.rotateZ(p.z)
        ° .rotateY(p.y)
        ° .rotateX(p.x)
    }

    static func reverseZ() -> Matrix {
        Matrix([
            [ 1, 0, 0, 0],
            [ 0, 1, 0, 0],
            [ 0, 0, -1, 0],
            [ 0, 0, 0, 1 ]
        ])
    }
    
    static func setWtoZ() -> Matrix {
        Matrix([
            [ 1, 0, 0, 0],
            [ 0, 1, 0, 0],
            [ 0, 0, -1, -1],
            [ 0, 0, 0, 0 ]
        ])
    }
    
    static func projectionMatrix(fov: CGFloat, near: CGFloat, far: CGFloat) -> Matrix {
        let scale = 1 / tan(fov/2.0 * CGFloat.pi / 180.0)
        let r = Matrix([
            [ scale, 0, 0, 0],
            [ 0, scale, 0, 0],
            [ 0, 0, -far / (far - near), -1],
            [ 0, 0, -(far * near / (far - near)), 0 ]
        ])
        return r
    }
     
    static func camera(fov: CGFloat, near: CGFloat, far: CGFloat) -> Matrix {
        Self.reverseZ()
        ° setWtoZ()
        ° projectionMatrix(fov: fov, near: near, far: far)
    }
}

and it is how I call them to get all necessary transformations:

 var result = point3d.matrix
            ° .rotate(objectRotation)
            ° .translate(by: objectTranslation)
            ° .translateToCamera(position: viewPosition)
            ° .camera(fov: fov, near: near, far:far)

I use SwiftMatrix package for matrices. ° symbol means matrix multiplication. Maybe I'm wrong, but In suspect that somebody familiar with 3D could immediately spot the error. I could not. Knowlege mainly from this site

Y, and Z behaves well:

Y-rotate

Z-rotate

1 Answer 1

2

The matrix in your func rotateX seems to be lacking a minus for one of the sin(angle).

3
  • indeed, you are right! (is it important which one?)
    – Łukasz
    Commented Dec 6, 2023 at 20:57
  • If you put it on the upper right, the rotation will be counterclockwise, for the lower left one it will be clockwise (assuming a positive angle).
    – Tatschi
    Commented Dec 6, 2023 at 21:02
  • It's why it was rotated in BOTH directions at once. Thanks!
    – Łukasz
    Commented Dec 6, 2023 at 21:04

Not the answer you're looking for? Browse other questions tagged or ask your own question.