1

我希望在 Scenekit 中创建 AR 圆顶形状几何,就像在 qlone 3D 扫描仪应用程序中创建一样。请参阅以下链接以获取视觉效果。

https://www.youtube.com/watch?v=0JQZmTT3KO0

https://3dscanexpert.com/qlone-3d-scanning-ios-app/

在此处输入图像描述

4

1 回答 1

0

Model IO api MDLMesh.newEllipsoid 创建圆顶,现在我们需要在圆顶的每个部分上放置瓷砖。

  1. 创建圆顶并获取顶点,并使用顶点创建图块并将它们作为单独的 SCNNode 放置。
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)])
        }
    }
}
于 2021-07-11T02:30:04.463 回答