¿Dibujar un cilindro de línea de trazos en scenekit como la aplicación de medición?

Aug 20 2020

He seguido esta pregunta para intentar hacer que el cilindro del tablero

final class LineNode: SCNNode {

    convenience init(positionA: SCNVector3, positionB: SCNVector3) {
        self.init()

        let vector = SCNVector3(positionA.x - positionB.x, positionA.y - positionB.y, positionA.z - positionB.z)
        let distance = vector.length
        let midPosition = (positionA + positionB) / 2

        let lineGeometry = SCNCylinder()
        lineGeometry.radius = PileDrawer3D.lineWidth
        lineGeometry.height = CGFloat(distance)
        lineGeometry.radialSegmentCount = 5

        lineGeometry.firstMaterial?.diffuse.contents = dashedImage
        lineGeometry.firstMaterial?.diffuse.contentsTransform = SCNMatrix4MakeScale(distance * 10, Float(lineGeometry.radius * 10), 1)
        lineGeometry.firstMaterial?.diffuse.wrapS = .repeat
        lineGeometry.firstMaterial?.diffuse.wrapT = .repeat
        lineGeometry.firstMaterial?.isDoubleSided = true
        lineGeometry.firstMaterial?.multiply.contents = UIColor.green
        lineGeometry.firstMaterial?.lightingModel = .constant

        let rotation = SCNMatrix4MakeRotation(.pi / 2, 0, 0, 1)
        lineGeometry.firstMaterial?.diffuse.contentsTransform = SCNMatrix4Mult(rotation, lineGeometry.firstMaterial!.diffuse.contentsTransform)

        geometry = lineGeometry
        position = midPosition
        eulerAngles = SCNVector3.lineEulerAngles(vector: vector)

        name = className
    }

    lazy var dashedImage: UIImage = {

        let size = CGSize(width: 10, height: 3)
        UIGraphicsBeginImageContextWithOptions(size, true, 0)
        UIColor.white.setFill()
        UIRectFill(CGRect(x: 0, y: 0, width: 7, height: size.height))
        let img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return img!
    }()

}

Sin embargo, las tuberías no están discontinuas.

No estoy seguro de qué me estoy perdiendo aquí, por favor ayuda.

UpdateT:

Resulta que el color claro (en la imagen) se representa como negro, no transparente en SCNView. Aún así, no tengo idea de por qué el color verde se oscureció así.

Respuestas

Eddie Sep 03 2020 at 14:08

Otro enfoque para Line & DashLine

final class LineNode: SCNNode {

    var color: UIColor? {
        set { geometry?.firstMaterial?.diffuse.contents = newValue }
        get { geometry?.firstMaterial?.diffuse.contents as? UIColor }
    }

    convenience init(positionA: SCNVector3, positionB: SCNVector3, dash: CGFloat = 0, in scene: SCNScene? = nil) {
        self.init()
        let indices: [Int32] = [0, 1]
        let source = SCNGeometrySource(vertices: [positionA, positionB])
        let element = SCNGeometryElement(indices: indices, primitiveType: .line)
        geometry = SCNGeometry(sources: [source], elements: [element])
        geometry?.firstMaterial?.diffuse.contents = UIColor.green
        geometry?.firstMaterial?.lightingModel = .constant

        return
    }
}

final class DashLineNode: SCNNode {
    convenience init(positionA: SCNVector3, positionB: SCNVector3) {
        self.init()
        let vector = (positionB - positionA)
        let length = floor(vector.length / 1)
        let segment = vector / length

        let indices:[Int32] = Array(0..<Int32(length))
        var vertices = [positionA]
        for _ in indices {
            vertices.append(vertices.last! + segment)
        }
        let source = SCNGeometrySource(vertices: vertices)
        let element = SCNGeometryElement(indices: indices, primitiveType: .line)

        geometry = SCNGeometry(sources: [source], elements: [element])
        geometry?.firstMaterial?.lightingModel = .constant
    }
}