SceneKit관련 질문입니다.
아직 SceneKit에 대한 정확인 이해가 없어서 그런데 사이트에 올라와 있는 방식으로는
func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval)
를 통해 계속 렌더링하면서 트레킹 매니져에서 이미지가 디텍팅 되어있을 때, 해당 좌표를 기준으로 대상 객체를 렌더링을 하는 것으로 보여집니다.
제가 원하는 방법은 타겟 이미지가 디텍팅되어있을 때, addChildNode방식으로 특정 객체를 띄우려고 합니다. 하지만 위 함수의 파라미터에서 scene은
타겟팅된 객제가 아닌 것으로 보여지는데요... 올려주신 예제를 통하여 제가 원하는 방식으로 특정 객체를 띄울 수 있을까요?
addChildNode 방식으로 타겟이 디텍팅 되었을때 추가하시려면, Scenekit 샘플에서 MarkerViewController.swift 보시면 cameraNode에 addChildNode하는 부분이 viewDidLoad에 있습니다. 그부분을
func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval)
에서 적용하시면 될것 같습니다.
let foxScene = SCNScene(named: "art.scnassets/ship.scn")!
firstNode = foxScene.rootNode
firstTransform = firstNode.transform
cameraNode.addChildNode(firstNode)
이부분을 renderer에서 구현 하시면 됩니다. 이미지에 대한 타겟 네임은
let trackable:MasTrackable = result.getTrackable(i)
trackable.getName() 을 통해서 얻으실 수 있습니다.
가이드해주신대로 하니 객체표현은 잘 됩니다. 그런데 일단 타겟이 인식되면 그 위에 계속 보여지는 것이고, '타겟 이미지에 위치에만' 객체가 보여지게하는 것은 안되네요.
기존 예제를 보니 아마 trackable에서 matrix로 해당 '타겟 좌표를 얻어' 렌더링 하는 것 같은데, addChildNode방식으로는 불가능한 것 일까요?
말씀하신 부분이 정확하게 트래킹이 않된다는것인가요?
트래킹 부분은
firstNode.transform = SCNMatrix4Mult(firstTransform, poseSCNMatrix4)
firstNode.scale = SCNVector3Make(3.0, 3.0, 3.0)
이렇게 적용하셔야 이미지에 붙어서 이동하게 됩니다.
firstTransform은 컨텐츠의 기존 위치이고 poseSCNMatrix4는 타겟 이미지의 중점위치입니다.
아래와 같은 방식으로 수정되면 되지 않나요?? (동작하는 모습을 레코딩했는데, 파일첨부는 할 수가 없군요...)
아래와같이 작성하면 이미지 디텍팅시 객체가 위에 나타나게되는데 카메라를 이리저리 돌려도 타겟 중심점위에 있는게 아니라 화면 자체에 붙어서 보여집니다.ㅠ(제가 원하는 것은 카메라를 이리저리 이동해도 타겟 이미지위에 딱 붙어서 보여지게 하고 싶은 것입니다.)
if trackable.getName() == "Lego" {
let foxScene = SCNScene(named: "art.scnassets/ship.scn")!
if foxNode == nil {
foxNode = foxScene.rootNode
foxTransform = foxNode.transform
foxNode.transform = SCNMatrix4Mult(foxTransform, poseSCNMatrix4)
foxNode.position = SCNVector3(0.0, 0.0, -3.0)
foxNode.scale = SCNVector3(3.0, 3.0, 3.0)
cameraNode.addChildNode(foxNode)
}
}
if trackable.getName() == "Lego" {
if(foxScene == nil) {
foxScene = SCNScene(named: "art.scnassets/ship.scn")!
firstNode = foxScene.rootNode
firstTransform = firstNode.transform
cameraNode.addChildNode(firstNode)
}
if(firstNode != nil) {
firstNode.transform = SCNMatrix4Mult(firstTransform, poseSCNMatrix4)
firstNode.scale = SCNVector3Make(3.0, 3.0, 3.0)
}
}
이런식으로 하셔야 합니다. ship.scn을 계속 로드할 필요는 없으시고, 해당 컨텐츠가 로드 되고 나면 "Lego"라는 이미지가 보여지면 poseSCNMatrix4이 매트릭스를 해당 Node에 적용시켜서 이미지에 붙어다니게 해야합니다.
음..말씀해주신대로 수정하니 컨텐츠가 해당 이미지위에 그려지고 있습니다. 하지만 역시나 한 부분에 딱 고정되어 있는 것은 아니고, 타겟 이미지내에 움직이긴 하네요;;(파일 첨부). 말씀하신 것이 아래 그림과 같이 나타나는 결과인 것인가요?
그리고 트래킹 부분이 벗어낫을 때, 해당 컨텐츠를 제거하고 싶은데, 아래와같이 구현하면 EXC_BAD_ACCESS 에러가나네요...
단순히 removeFromParentNode()만 호출해서는 안되는 것인가요??
cameraNode.enumerateChildNodes({ (child: SCNNode, _: UnsafeMutablePointer<ObjCBool>) in
if let name = child.name {
print("name:\(name)")
}
if child.name == "ship" {
child.removeFromParentNode()
}
})
어떤식으로 구현해야 할까요??
답변 부탁드겠습니다ㅠ
답변이 늦어져서 죄송합니다.
1. 이미지에 붙어서 트래킹 되는것이 맞습니다. 무언가 잘못 적용된것 같네요.
2. 노드를 제거하기 위해서는 메인 스레드에서 해야하는것 같습니다.
관련된 소스 첨부해 드립니다.
https://www.dropbox.com/s/evnq908iioszve1/ImageViewController.swift?dl=0
네! 감사합니다!! 궁금한 내용은 다 해결되었네요!!
주신 소스를 가지고 참고하도록 하겠습니다! :)