ARKit을 사용하여 공간에 선을 그리는 방법(초급편)

11496 단어 iOSSwiftARKit
ARKit을 사용하여 선을 쓸 수 있는 앱으로 유명한 것이 Just a line , World Brush 등. 그 외에도 Facebook의 카메라에서도 공간에 낙서할 수 있거나 낙서 앱이라는 몇 가지가 있습니다.

또한 내가 속한 Graffity에서도 공간에 낙서하는 앱을 만들어 왔습니다.

지금 기사에서는 어떤 원리로 공간에 낙서하고 있는지 설명합니다.

가장 간단한 선을 쓰는 법



"카메라로부터 일정한 거리에 구를 놓고 그 연속으로 선을 만든다"라는 방법이 가장 간단합니다.


연속으로 점을 치다
점을 치는 스팬을 짧게





// タップした状態で指を動かすと呼ばれるメソッド
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let point = touches.first?.location(in: sceneView) else {
        return
    }
    let point3D = sceneView.unprojectPoint(SCNVector3(point.x, point.y, 0.997))

    // 球のNodeを作る
    let ball = SCNSphere(radius: 0.005)
    ball.firstMaterial?.diffuse.contents = UIColor.red
    let node = SCNNode(geometry: ball)
    node.position = point3D
    sceneView.scene.rootNode.addChildNode(node)
}

프레임 업데이트를 이용하는 방법





방금 전의 방법이라면, 손가락의 움직임을 트랙하고 있을 뿐이므로, 디바이스를 움직였을 때에 움직인 것으로 간주되지 않고, 그림의 폭이 넓어지지 않습니다.

다음과 같이 춤을 추면서 그림을 그릴 수 없습니다.

예술적 느낌 피 c. 라고 r. 코 m / 구시 5 오 tH — K-BOY@AR 엔지니어 (@kboy_silvergym) 2018년 12월 9일


그래서 프레임 업데이트를 활용하는 방법이 있습니다. 터치 중에는 플래그를 세워 두고(필요에 따라 터치의 위치를 ​​앞의 touchesMoved 메소드로 취득해), 프레임이 갱신할 때마다 불리는 ARSCNViewDelegate의 renderer(:updateTime) 안에 구를 두어 가는 패턴 입니다.



참고로 ARKit에서는 기본적으로 60fps이므로 초당 60회 프레임이 업데이트되어 카메라가 동영상으로 보입니다. 즉, 이 방법으로는 초당 60회 구를 놓아두게 됩니다.



private var pointTouching: CGPoint = .zero

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    isTouching = true

    guard let location = touches.first?.location(in: nil) else {
        return
    }
    pointTouching = location
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let location = touches.first?.location(in: nil) else {
        return
    }
    pointTouching = location
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    isTouching = false
}

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    guard isTouching else {return}

    // 球のNodeを作って置く
    let point3D = sceneView.unprojectPoint(SCNVector3(pointTouching.x, pointTouching.y, 0.997))

    // 球のNodeを作る
    let ball = SCNSphere(radius: 0.005)
    ball.firstMaterial?.diffuse.contents = UIColor.red
    let node = SCNNode(geometry: ball)
    node.position = point3D
    sceneView.scene.rootNode.addChildNode(node)
}


공을 연속적으로 배치하는 데 어려움



여기까지 언급했듯이 "구를 연속으로 놓는 것"으로 선이 완성됩니다. 그러나 SCNNode를 짧은 시간에 연속으로 두면 매우 무거워집니다. 그리고 그렇게 깨끗한 선이 아닙니다.



여기서 3DBrush 라는 앱을 살펴보겠습니다.





3DBrush는 구의 연속으로 선을 쓰는 것이 아니라, 1개의 선단위의 곡선의 지오메트리를 가지는 SCNNode를 만들어 두고 있는 것처럼 보입니다. 보다 메모리 효율이 좋고, 깨끗한 선을 그리기 위해서는 이 접근법이 좋을 것 같습니다.



그럼 어떻게 이런 접근을 할까요?



이것은 또한 내일 기사에서 상급편 으로 쓰고 싶습니다.



그럼!


좋은 웹페이지 즐겨찾기