Как нарисовать пунктирную линию в ARKit (SceneKit), как в приложении Measure?

Просто хотел узнать, возможно ли (я знаю, что это так, но как) нарисовать пунктирную линию в ARSCNView, как в приложении Measure? Может быть, есть способ использовать узлы сцены из коробки, idk.

Я использовал SCNCylinder, чтобы нарисовать прямую линию, и IDK, возможно ли повторно использовать ее и скорректировать, или мы должны использовать действительно другой способ сделать пунктирную линию.

import SceneKit

class CylinderLineNode: SCNNode {

    private(set) var cylinder: SCNCylinder
    private(set) var positionA: SCNVector3
    private(set) var positionB: SCNVector3

    init(with positionA: SCNVector3, positionB: SCNVector3, radius: CGFloat = 0.02, color: UIColor = .red) {
        self.positionA = positionA
        self.positionB = positionB
        let vector = positionB - positionA
        let height = vector.length()
        cylinder = SCNCylinder(radius: radius, height: CGFloat(height))
        cylinder.radialSegmentCount = 8
        cylinder.firstMaterial?.diffuse.contents = color
        super.init()
        geometry = cylinder
        position = (positionB + positionA) / 2
        eulerAngles = SCNVector3.lineEulerAngles(vector: vector)
    }

    ...

}

1 ответ

Решение

Возможно, не самое профессиональное решение, но я начал с очень похожего подхода. И затем добавил пунктирный стиль, как следует.

Сначала я создал изображение наполовину белое, наполовину прозрачное, чтобы создать штриховой стиль

Затем использовал его в материале SCNCylinder:

material.diffuse.contents = UIImage(named: "line")!
material.diffuse.wrapS = .repeat
material.diffuse.wrapT = .repeat
material.isDoubleSided = true // Not sure if this is really needed here^

Затем я соответственно масштабировал его, чтобы повторить (сделать так, чтобы все было в порядке), как я хочу:

material.diffuse.contentsTransform = SCNMatrix4MakeScale(width * repeatCountPerMeter, height * repeatCountPerMeter, 1)

Поскольку я использовал белое изображение, я могу "подкрасить" его в любой цвет, какой захочу:

material.multiply.contents = UIColor.green

Чтобы сделать его более похожим на 2D, игнорируйте освещение, используя:

material.lighting = .constant

Кроме того (поскольку мой цилиндр поворачивается на 90°), мне также пришлось повернуть материал:

let rotation = SCNMatrix4MakeRotation(.pi / 2, 0, 0, 1)
material.diffuse.contentsTransform = SCNMatrix4Mult(rotation, material.diffuse.contentsTransform)

И всякий раз, когда строка изменяется, обновите ее SCNMatrix4MakeScale соответственно (см. width и высотаabove, where forвысота` я просто поставил диаметр (2* р)).

Другие вопросы по тегам