iosswiftmetalglkitmetalkit

Apple Metal iOS why does GLKMatrix4MakeLookAt rock back and forth


I am developing a 3D scene on iOS 16.1 with Xcode 14.3. I have a rectangular plane orbiting the origin at an incline and I want to use GLKMatrix4MakeLookAt to cause the plane to always face the origin.

I am using the code below. The plane does 'face' the origin when it rotates, however I am also seeing this undesired 'rocking' ( yaw ) back and forth. Please see the attached video to understand how it looks.

Why does it do this rocking? How can I get rid of the rocking but still have the plane orbit the origin and always face it? Thank you.

enter image description here

Code:

// Get the lookat scene origin matrix for the rectangle
var lookAtSceneOriginGLKMatrix = GLKMatrix4Identity
var lookAtSceneOriginInverse = GLKMatrix4Identity
var rectangleModelMatrix = float4x4()
var lookAtSceneOriginMat = float4x4()

lookAtSceneOriginGLKMatrix = GLKMatrix4Multiply(lookAtSceneOriginGLKMatrix, GLKMatrix4MakeLookAt(self.currentSatX * self.appDelegate.getCurrentRectangle().getRenderHeight(), self.currentSatY * self.appDelegate.getCurrentRectangle().getRenderHeight(), self.currentSatZ * self.appDelegate.getCurrentRectangle().getRenderHeight(), 0, 0, 0, 0, 1, 0))
var isInvertible = true
lookAtSceneOriginInverse = GLKMatrix4Invert(lookAtSceneOriginGLKMatrix, &isInvertible)
lookAtSceneOriginMat = float4x4(convertToFloat4x4FromGLKMatrix: lookAtSceneOriginInverse)
rectangleModelMatrix = accumulatedRotationMatrix * lookAtSceneOriginMat * float4x4(scaleBy: 0.35)

// Draw the rectangular plane
scene.rectanglePlane?.draw(
    encoder: commandEncoder, modelMatrix: rectangleModelMatrix,
    projectionMatrix: projectionMatrix * viewMatrix
)

Solution

  • As mentioned in a Comment your up vector always pointing to the direction of y axis. It should be perpendicular to the direction vector.

    let x = self.currentSatX * self.appDelegate.getCurrentRectangle().getRenderHeight()
    let y = self.currentSaty * self.appDelegate.getCurrentRectangle().getRenderHeight()
    let z = self.currentSatZ * self.appDelegate.getCurrentRectangle().getRenderHeight()
    
    let direction = GLKVector3Make(x, y, z) //vector from planes postion to origin
    
    let yAx = GLKVector3Make(0, 1, 0) // y axis
    
    let side = GLKVector3CrossProduct(direction, yAx) //perpendicular vector to direction
    
    let up = GLKVector3CrossProduct(side, direction) //perpendicular vector to side
    let normalizedUp = GLKVector3Normalize(up)
    
    lookAtSceneOriginGLKMatrix = GLKMatrix4Multiply(lookAtSceneOriginGLKMatrix, GLKMatrix4MakeLookAt(x, y, z, 0, 0, 0, normalizedUp.x, normalizedUp.y, normalizedUp.z))