How to use SCNSceneSource.LoadingOption.createNormalsIfAbsent?
The file prim.scn has a simple toroid geometry that has no normals. When I load and inspect it it still has no normals. I've also tried with an empty SCNGeometrySource for normals. It doesn't add them.
scnScene = SCNScene()
let documentsPath = FileManager.default.urls(for: .documentDirectory,
in: .userDomainMask).first!
let url = documentsPath.appendingPathComponent("prim.scn")
do {
scnScene = try SCNScene(url: url,
options: [.createNormalsIfAbsent: true])
} catch {
print("error")
}
Inspecting in lldb yields:
(lldb) p scnScene.rootNode.childNodes[3].geometry?.sources
([SCNGeometrySource]?) $R1 = 1 value {
[0] = 0x0000600001a09f80
}
(lldb) p scnScene.rootNode.childNodes[3].geometry?.sources[0]
(SCNGeometrySource?) $R2 = 0x0000600001a09f80 {
baseNSObject@0 = {
isa = SCNGeometrySource
}
_data = 0x00007fdef1847c00 4800 bytes
_semantic = 0x00007ff9540c3ec0 "kGeometrySourceSemanticVertex"
_vectorCount = 400
_componentType = 1
_componentCount = 3
_colorSpace = 0x0000000000000000
_dataOffset = 0
_dataStride = 12
_mkSemantic = '\0'
_mtlBuffer = 0x0000000000000000
_mtlVertexFormat = 0
_encodeDataAsHalf = '\0'
}
I would expect there to be a
scnScene.rootNode.childNodes[3].geometry?.sources[0]
containing the normals.
Here's prim.scn file.
You already got info about normals count in your model. The names of parameters are _vectorCount
and _componentCount
. Use the following code to calculate the number of normals. For additional info, read this post.
macOS 13.0 Ventura, Xcode 14.1 RC 2.
import SceneKit
class ViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let sceneView = self.view as! SCNView
sceneView.autoenablesDefaultLighting = true
sceneView.backgroundColor = .black
let path = FileManager.default.urls(for: .documentDirectory,
in: .userDomainMask).first!
let url = path.appendingPathComponent("prim.scn")
do {
let scene = try SCNScene(url: url,
options: [.createNormalsIfAbsent: true])
sceneView.scene = scene
let sceneNodes: [SCNNode] = scene.rootNode.childNodes
for s in (sceneNodes[3].geometry?.sources.enumerated())! {
// 1200 normals (400 vectors * 3 normals)
print(s.element.vectorCount * s.element.componentsPerVector)
}
} catch {
print(error.localizedDescription)
}
}
}
P. S.
Your model initially has normals – that's why [.createNormalsIfAbsent: true]
has no effect.
SceneKit's directional light wouldn't work without normals.