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 |
| } |
| } |
| } |