Code Block @available(iOS 13.4, *) |
extension SCNGeometry { |
|
/** |
Constructs an SCNGeometry element from an ARMeshAnchor. |
|
if setColors, will set colors automatically on each face based on ARMeshClassification above |
*/ |
public static func fromAnchor(meshAnchor: ARMeshAnchor, setColors: Bool) -> SCNGeometry { |
let meshGeometry = meshAnchor.geometry |
let vertices = meshGeometry.vertices |
let normals = meshGeometry.normals |
let faces = meshGeometry.faces |
|
// use the MTL buffer that ARKit gives us |
let vertexSource = SCNGeometrySource(buffer: vertices.buffer, vertexFormat: vertices.format, semantic: .vertex, vertexCount: vertices.count, dataOffset: vertices.offset, dataStride: vertices.stride) |
|
let normalsSource = SCNGeometrySource(buffer: normals.buffer, vertexFormat: normals.format, semantic: .normal, vertexCount: normals.count, dataOffset: normals.offset, dataStride: normals.stride) |
|
|
// Copy bytes as we may use them later |
let faceData = Data(bytes: faces.buffer.contents(), count: faces.buffer.length) |
|
// create the geometry element |
let geometryElement = SCNGeometryElement(data: faceData, primitiveType: .of(faces.primitiveType), primitiveCount: faces.count, bytesPerIndex: faces.bytesPerIndex) |
|
|
let geometry : SCNGeometry |
|
if setColors { |
// calculate colors for each indivudal face, instead of the entire mesh |
|
var colors = [SIMD4<Float>]() |
|
for i in 0..<faces.count { |
colors.append(meshGeometry.classificationOf(faceWithIndex: i).colorVector) |
} |
|
let colorSource = SCNGeometrySource(data: Data(bytes: &colors, count: colors.count * SIMD4_FLOAT_STRIDE), |
semantic: .color, |
vectorCount: colors.count, |
usesFloatComponents: true, |
componentsPerVector: 4, |
bytesPerComponent: FLOAT_STRIDE, |
dataOffset: 0, |
dataStride: SIMD4_FLOAT_STRIDE |
) |
|
geometry = SCNGeometry(sources: [vertexSource, normalsSource, colorSource], elements: [geometryElement]) |
} |
else { |
geometry = SCNGeometry(sources: [vertexSource, normalsSource], elements: [geometryElement]) |
} |
|
|
return geometry; |
} |
} |
|
let SIMD4_FLOAT_STRIDE = MemoryLayout<SIMD4<Float>>.stride |
let FLOAT_STRIDE = MemoryLayout<Float>.stride |
let VECTOR_WHITE : SIMD4<Float> = SIMD4<Float>(1.0, 1.0, 1.0, 1.0) |
let VECTOR_YELLOW: SIMD4<Float> = SIMD4<Float>(1.0, 1.0, 0, 1.0) |
let VECTOR_BLUE: SIMD4<Float> = SIMD4<Float>(0, 0, 1.0, 1.0) |
|
@available(iOS 13.4, *) |
extension ARMeshClassification { |
var description: String { |
switch self { |
case .ceiling: return "Ceiling" |
case .door: return "Door" |
case .floor: return "Floor" |
case .seat: return "Seat" |
case .table: return "Table" |
case .wall: return "Wall" |
case .window: return "Window" |
case .none: return "None" |
@unknown default: return "Unknown" |
} |
} |
|
// make more or less same vertical/horizontal colors as planes |
var color: UIColor { |
switch self { |
case .ceiling: return .blue |
case .door: return .white |
case .floor: return .blue |
case .seat: return .white |
case .table: return .white |
case .wall: return .yellow |
case .window: return .white |
case .none: return .white |
@unknown default: return .white |
} |
} |
|
var colorVector: SIMD4<Float> { |
switch self { |
case .ceiling: return VECTOR_BLUE |
case .door: return VECTOR_WHITE |
case .floor: return VECTOR_BLUE |
case .seat: return VECTOR_WHITE |
case .table: return VECTOR_WHITE |
case .wall: return VECTOR_YELLOW |
case .window: return VECTOR_WHITE |
case .none: return VECTOR_WHITE |
@unknown default: return VECTOR_WHITE |
} |
} |
} |