iosopengl-esscenekitglkit

How can I combine SceneKit with existing OpenGL using SCNRenderer?


I would like to use SceneKit’s SCNRenderer to draw a few models into my existing GLKit OpenGL ES 3.0 application and match my existing modelViewProjection transform. When I load a SceneKit scene and render it using SCNRenderer the SceneKit camera transformations seem to be ignored and I just get a default bounding box view. More generally of course I would prefer to supply my own matrix and I am not sure how to do that.

//
// Called from my glkView(view: GLKView, drawInRect rect: CGRect)
//

// Load the scene
let scene = SCNScene(named: "art.scnassets/model.scn")!

// Create and add regular SceneKit camera to the scene
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(x: 0, y: 0, z: 10)
scene.rootNode.addChildNode(cameraNode)

// Render into the current OpenGL context
let renderer = SCNRenderer( context: EAGLContext.currentContext(), options: nil )
renderer.scene = scene
renderer.renderAtTime(0)

I see that there is a projectionTransform exposed on the SCN Camera and I have tried manipulating that as well, but with no results. I’m also guessing that that is just literally a projection transform and not expecting the full modelViewProjection transform.

// Probably WRONG
cameraNode.camera!.projectionTransform = SCNMatrix4FromGLKMatrix4( modelViewProjectionTransform )

Does anyone have an example of mixing SceneKit into OpenGL drawing in this way? Thanks.

EDIT:

Bobelyuk's reference to the example is on point and has helped me solve half of my problem so far. It turns out that although I was adding the camera node I had failed to set the camera node as the 'pointOfView':

scene.pointOfView = cameraNode

The example appears to show how to take an opengl matrix and invert it to set it on the camera, however as of yet I have not been able to get this to work with my code. I will update again with a code example shortly.


Solution

  • Ultimately it turned out to be very simple. In addition to setting the pointOfView to the camera node I just needed to properly set the camera transform and camera projection transform to my own matrices.

    Here is the updated example:

    //
    // Called from my glkView(view: GLKView, drawInRect rect: CGRect)
    //
    
    // Load the scene
    let scene = SCNScene(named: "art.scnassets/model.scn")!
    let cameraNode = SCNNode()
    cameraNode.camera = SCNCamera()
    scene.rootNode.addChildNode(cameraNode)
    
    // Set my own matrices
    cameraNode.transform = SCNMatrix4Invert(SCNMatrix4FromGLKMatrix4(myModelViewMatrix))
    cameraNode.camera!.projectionTransform = SCNMatrix4FromGLKMatrix4(myProjectionMatrix)
    
    // Render into the current OpenGL context
    let renderer = SCNRenderer( context: EAGLContext.currentContext(), options: nil )
    renderer.scene = scene
    renderer.pointOfView = cameraNode  // set the point of view for the scene
    renderer.renderAtTime(0)
    

    For thos new to this: The model view matrix is the matrix that orients your scene, e.g. composing GLKMatrix4Scale and GLKMatrix4Rotate calls. The projection matrix is the one that sets your view frustrum and point of view, e.g. by composing calls to GLKMatrix4MakePerspective and GLKMatrix4MakeLookAt calls.