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.
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:
The matrix in your func rotateX
seems to be lacking a minus for one of the sin(angle)
.