Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of SCNMorpher produces undesired flat polygon rendering in SceneKit

Tags:

scenekit

I am using SCNMorpher in iOS SceneKit to morph between different facial expressions on a 3D face model exported as a DAE file from Blender. The morphing itself works fine.

Before I first call setWeight:forTargetAtIndex: on the morpher, the model is rendered smoothly, as desired.

But as soon as I make that call, all the polygon edges become visible, which is very unattractive. It's the same difference as switching from 'smooth' to 'flat' rendering in Blender itself.

Images follow: first the smooth rendering, pre-morph, then the flat rendering, post-morph.

Smooth rendering, pre-morphFlat rendering, post-morph

I'm using the Lambert lighting model (though the others are affected just the same), and litPerPixel is true for every material of every target geometry.

I'm not clear if this is a known/deliberate limitation of SCNMorpher, a bug, or something I'm doing wrong. I wonder whether the morph is somehow screwing up the vertex normal data which would normally be used for smooth rendering.

Any light anyone could shed would be much appreciated. (I guess a possible workaround might be to do the morphing manually by interpolating all the vertex and normal vectors to form a new geometry, but I imagine this will be unpleasantly slow).

The relevant part of the code is as follows:

faceNode.geometry = faces.rootNode.childNodeWithName("neutral", recursively: true)!.geometry
scene.rootNode.addChildNode(faceNode)

var morphs: [SCNGeometry] = []

let moods: [String] = "mood1 mood2".componentsSeparatedByString(" ")
for mood in moods {
  let moodFace = faces.rootNode.childNodeWithName(mood, recursively: true)!.geometry!
  morphs.append(moodFace)
}

let morpher = SCNMorpher()
morpher.targets = morphs

faceNode.morpher = morpher
morpher.setWeight(0.5, forTargetAtIndex: 0)
like image 478
jawj Avatar asked Jul 14 '15 09:07

jawj


1 Answers

Just ran into this problem as well. You need to set unifiesNormals to true on the morpher.

let morpher = SCNMorpher()
morpher.targets = morphs
morpher.unifiesNormals = true
faceNode.morpher = morpher
like image 162
TurnYellow Avatar answered Oct 04 '22 06:10

TurnYellow