When changing the divisions argument in MDLVoxelArray() I sometimes get a stray voxel that is unrelated to the underlying Nodes/Geometries. Why is this?
Setup
Consider this Playground code to build a mesh (SCNGeometry)
import UIKit
import SceneKit
import PlaygroundSupport
import SceneKit.ModelIO
let sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 800, height: 800))
let scene = SCNScene()
sceneView.backgroundColor = .black
sceneView.scene = scene
sceneView.allowsCameraControl = true
PlaygroundPage.current.liveView = sceneView
var cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(x: 0, y: 0, z: 10)
scene.rootNode.addChildNode(cameraNode)
var ambientLight = SCNNode()
ambientLight.light = SCNLight()
ambientLight.light?.type = .ambient
cameraNode.addChildNode(ambientLight)
let vertices: [SCNVector3] = [
// back square
SCNVector3(-1, -1, 0),
SCNVector3( 1, -1, 0),
SCNVector3( 1, 1, 0),
SCNVector3(-1, 1, 0),
// top triangle
SCNVector3(-1, 1, 0),
SCNVector3(-1, 1, 1),
SCNVector3(1, 1, 0),
// left triangle
SCNVector3(-1, 1, 0),
SCNVector3(-1, 1, 1),
SCNVector3(-1, 0, 0),
// detached-right triangle
SCNVector3(1.1, -1.1, 0), // deliberately an extra .1 so the divisions aren't regular
SCNVector3(1.5, -1.1, 0),
SCNVector3(1.5, 0.7, 0),
// detached front triangle
SCNVector3(-0.5, -0.5, 2),
SCNVector3(0.5, -0.5, 2.5),
SCNVector3(0.0, 0.0, 2.2)
]
let vertexSource = SCNGeometrySource(vertices: vertices)
// Faces
let indices: [Int32] = [
0,1,2,
0,2,3,
4,5,6,
7,8,9,
10,11,12,
13,14,15
]
let indexElement = SCNGeometryElement(
indices: indices,
primitiveType: .triangles
)
// Normals
let normals: [SCNVector3] = [
SCNVector3(0, 0, 1)
]
let normalSource = SCNGeometrySource(normals: normals)
// Colors
let colours: [SCNVector3] = [
SCNVector3(1, 0, 0),
SCNVector3(0, 1, 0),
SCNVector3(0, 0, 1),
SCNVector3(1, 0, 0),
SCNVector3(0, 0, 1),
SCNVector3(0, 1, 0),
SCNVector3(1, 0, 1),
SCNVector3(0, 1, 1),
SCNVector3(0, 0, 1),
SCNVector3(1, 0, 1),
SCNVector3(0, 1, 1),
SCNVector3(0, 0, 1),
SCNVector3(1, 0, 1),
SCNVector3(0, 1, 1),
SCNVector3(0, 0, 1),
]
let colourData = Data(
bytes: colours,
count: MemoryLayout<SCNVector3>.size * colours.count
)
let colourSource = SCNGeometrySource(
data: colourData,
semantic: .color,
vectorCount: colours.count,
usesFloatComponents: true,
componentsPerVector: 3,
bytesPerComponent: MemoryLayout<Float>.size,
dataOffset: 0,
dataStride: MemoryLayout<SCNVector3>.size
)
let meshGeometry = SCNGeometry(
sources: [vertexSource, normalSource, colourSource],
elements: [indexElement]
)
let meshMaterial = SCNMaterial()
meshMaterial.diffuse.contents = UIColor.white
meshMaterial.isDoubleSided = true
meshGeometry.materials = [meshMaterial]
let meshNode = SCNNode(geometry: meshGeometry)
meshNode.position = SCNVector3(0, 0, 0)
meshNode.name = "meshNode"
sceneView.scene?.rootNode.addChildNode(meshNode)
Voxel Example
We can create a VoxelArray and place a sphere at each voxel position
let divisions: Int32 = 8 // when it's 9 there's a stray voxel?
let asset = MDLAsset(scnScene: scene)
let voxelArray = MDLVoxelArray(asset: asset, divisions: divisions, patchRadius: 0.0)
if let voxelData = voxelArray.voxelIndices() {
voxelData.withUnsafeBytes { voxelBytes in
let voxels = voxelBytes.bindMemory(to: MDLVoxelIndex.self).baseAddress!
let count = voxelData.count / MemoryLayout<MDLVoxelIndex>.size
for i in 0..<count {
let position = voxelArray.spatialLocation(ofIndex: voxels[i])
let vec3Position = SCNVector3Make(SCNFloat(position.x) , SCNFloat(position.y), SCNFloat(position.z) )
let sphere = SCNSphere(radius: 0.05)
sphere.firstMaterial?.diffuse.contents = UIColor.orange
let sphereNode = SCNNode(geometry: sphere)
sphereNode.position = vec3Position
scene.rootNode.addChildNode(sphereNode)
}
}
}
Issue
However, when I set the number of divisions to 9, I get a stray voxel. Why is this voxel generated?
let divisions: Int32 = 9




