0
votes

I am experimenting with the Google-VR iOS SDK. I have a very simple SceneKit scene containing a single textured object. This is rendered in the GVRCardboardViewDelegate drawEye method using an SCNRenderer. When vrModeEnabled is set to false on the GVRCardboardView then the object renders correctly but when set to true the texture is not applied correctly. See the image below.

After more investigation I've found that loading a scene containing a textured object from SceneKit .scn file works fine. The problem occurs when loading an OBJ file (and it's .mtl file and jpg texture) into an SCNNode by using ModelIO like this:

let stageURL = NSBundle.mainBundle().URLForResource("newStage", withExtension: "obj", subdirectory: "Art.scnassets")
let stageAsset = MDLAsset(URL: stageURL)
let stageObject = asset.objectAtIndex(0)
let stage = SCNNode(MDLObject: stageObject)
scene.addChildNode(stage)

It seems like it might be an OpenGL state problem (and possibly a bug in ModelIO) but I haven’t been able to find a solution or workaround. Any suggestions?

Example of texture appearance. Top vrModeEnabled = false, bottom vrModeEnabled = true

Example of texture appearance. Top vrModeEnabled = false, bottom vrModeEnabled = true

1

1 Answers

2
votes

Update: the actual solution was simple. For some unknown reason the texture transform was being messed up. Adding the following lines to the code in the question makes the texture appear as expected.

var transformForTexture = SCNMatrix4MakeScale(1, -1, 1);
transformForTexture = SCNMatrix4Translate(transformForTexture, 0, 1, 0)
stage.geometry?.firstMaterial?.diffuse.contentsTransform = transformForTexture

Original workaround:

Loading an OBJ file using ModelIO will implicitly use the associated material description file (which has the same file name as the OBJ file but with the extension .mtl) to provide textures and material properties for the geometry. Removing the material file and loading the texture explicitly fixed the problem.

let stageURL = NSBundle.mainBundle().URLForResource("newStage", withExtension: "obj", subdirectory: "Art.scnassets")
let stageAsset = MDLAsset(URL: stageURL)
let stageObject = asset.objectAtIndex(0)
let stage = SCNNode(MDLObject: stageObject)

let texture = SCNMaterial()
texture.diffuse.contents = UIImage(named: "Art.scnassets/stage.jpg")
stage.geometry?.firstMaterial = texture

scene.addChildNode(stage)

This is not an ideal solution but is an adequate workaround until I have time to debug the precise cause.

Note that prior to arriving at this solution I tried updating the texture properties in the SCNMaterialProperty on the node's diffuse material but this had no effect.