我希望在 Scenekit 中创建 AR 圆顶形状几何,就像在 qlone 3D 扫描仪应用程序中创建一样。请参阅以下链接以获取视觉效果。
https://www.youtube.com/watch?v=0JQZmTT3KO0
我希望在 Scenekit 中创建 AR 圆顶形状几何,就像在 qlone 3D 扫描仪应用程序中创建一样。请参阅以下链接以获取视觉效果。
https://www.youtube.com/watch?v=0JQZmTT3KO0
Model IO api MDLMesh.newEllipsoid 创建圆顶,现在我们需要在圆顶的每个部分上放置瓷砖。
import UIKit
import SceneKit
import ARKit
import ModelIO
class ARDome : SCNNode {
private var sceneView: ARSCNView!
private var radius: Float = 0.0
private var radialSegments: Int = 0
private var verticalSegments: Int = 0
private var maxDistanceToFocusPoint: Float = 0.05
private var minSize = SIMD3<Float>(0.01, 0.01, 0.01)
var tilesContinuousHitCount = [SCNNode:Int]()
private var extent = SIMD3<Float>(0.01, 0.01, 0.01) {
didSet {
extent = max(extent, minSize)
}
}
init(sceneView: ARSCNView, radius: Float, radialSegments: Int, verticalSegments: Int) {
super.init()
self.sceneView = sceneView
self.radius = radius
self.radialSegments = radialSegments
self.verticalSegments = verticalSegments
//self.categoryBitMask = 0x0
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func domeSkeleton() {
let mesh = MDLMesh.newEllipsoid(withRadii: vector_float3(radius, radius, radius), radialSegments: radialSegments, verticalSegments: verticalSegments, geometryType: MDLGeometryType.lines, inwardNormals: true, hemisphere: true, allocator: nil)
self.geometry = SCNGeometry(mdlMesh: mesh)
self.geometry?.firstMaterial?.diffuse.contents = UIColor.systemYellow
self.geometry?.firstMaterial?.isDoubleSided = true
}
func placeTiles() {
guard let geometry = self.geometry else { return }
let vertices = helper.testim(geo: geometry)
let rings = vertices.chunked(into: radialSegments + 1)
for base in 0..<(verticalSegments/2) {
let bottom = base + 1
let top = base
for i in 0..<(radialSegments) {
let rectNode = helper.getNode(lb: rings[bottom][i], lt: rings[top][i], rt: rings[top][i+1], rb: rings[bottom][i+1])
self.addChildNode(rectNode)
}
}
}
}
import Foundation
import ARKit
class DomeTile: SCNNode {
public var processed = false
init(geometry: SCNGeometry) {
super.init()
self.geometry = geometry
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
助手类
import UIKit
import SceneKit
import ARKit
import ModelIO
class helper {
public static func getNode(lb: SCNVector3, lt: SCNVector3, rt: SCNVector3, rb: SCNVector3) -> DomeTile{
let vertices: [SCNVector3] = [lb, lt, rt, rb,]
let source = SCNGeometrySource(vertices: vertices)
let indices: [UInt16] = [0, 1, 2, 0, 2, 3,]
let element = SCNGeometryElement(indices: indices, primitiveType: .triangles)
let geometry = SCNGeometry(sources: [source], elements: [element])
geometry.firstMaterial?.isDoubleSided = true
geometry.firstMaterial?.diffuse.contents = UIColor.systemBlue.withAlphaComponent(0.7)
let node = DomeTile(geometry: geometry)
return node
}
public static func testim(geo: SCNGeometry) -> [SCNVector3] {
//let rect = SCNBox(width: 40.0, height: 40.0, length: 5.0, chamferRadius: 0.0)
let srcs = geo.sources(for: .vertex)
guard let src = srcs.first else { exit(1)}
let bperC = src.bytesPerComponent
let stride = src.dataStride / bperC
let offset = src.dataOffset / bperC
let vectorCount = src.vectorCount
let vertices = src.data.withUnsafeBytes { (buffer : UnsafePointer<Float>) -> [SCNVector3] in
var result = Array<SCNVector3>()
for i in 0...vectorCount - 1 {
let start = i * stride + offset
let x = buffer[start]
let y = buffer[start + 1]
let z = buffer[start + 2]
result.append(SCNVector3(x, y, z))
}
return result
}
return vertices
}
}
extension Array {
func chunked(into size: Int) -> [[Element]] {
return stride(from: 0, to: count, by: size).map {
Array(self[$0 ..< Swift.min($0 + size, count)])
}
}
}