두 가지 문제가있는 것 같습니다. (Without even having used regular expressions. :))
먼저, 꼭지점의 텍스처 좌표, 즉 객체 표면의 2D 텍스처 공간에있는 점을 가져와야합니다. 당신은 거의 이미 그걸 가지고 있습니다. SCNHitTestResult
은 textureCoordinatesWithMappingChannel
방법을 제공합니다. (당신은 localCoordinates
을 사용하고 있습니다. 이는 히트 테스트 결과에서 노드가 소유 한 3D 공간에서 한 지점을 얻습니다.) 그리고 채널 매핑에 대한 사업을 이미 알았으므로 그 방법에 무엇을 전달해야하는지 알 것입니다 .
문제 2는 그립하는 방법입니다.
자료의 내용을 UIImage
으로 가져 오는 것은 옳은 일입니다. 일단 당신이 그것을 얻으면, 당신은 UIGraphics
과 CGContext
함수로 그림을 볼 수 있습니다. UIGraphicsBeginImageContext
으로 이미지를 만들고, 기존 이미지를 그려 넣은 다음, 새로운 점을 추가 할 위치에 추가하십시오. 그 다음에는 그림을 UIGraphicsGetImageFromCurrentImageContext
으로 가져와 새로운 재질로 diffuse.contents
으로 설정할 수 있습니다. 그러나 이것이 아마도 최선의 방법은 아닙니다. CPU에서 이미지 데이터를 많이 사용하고 있으며 코드도 다루기가 쉽지 않습니다.
더 나은 방법은 SceneKit과 SpriteKit 간의 통합을 활용하는 것입니다. 이렇게하면 모든 2D 드로잉이 3D 드로잉과 동일한 GPU 컨텍스트에서 일어나고 코드가 조금 더 간단 해집니다.
재료의 diffuse.contents
을 SpriteKit 장면으로 설정할 수 있습니다. (텍스처를 가지고있는 UIImage
을 사용하려면 장면을 채우는 SKSpriteNode
에 붙이면됩니다.) 텍스처 좌표를 얻으면 그 시점의 장면에 스프라이트를 추가 할 수 있습니다. (오브젝티브 C로) SpriteKit 방법에 대한 자세한 내용
var nodeToDrawOn: SCNNode!
var skScene: SKScene!
func mySetup() { // or viewDidLoad, or wherever you do setup
// whatever else you're doing for setup, plus:
// 1. remember which node we want to draw on
nodeToDrawOn = myScene.rootNode.childNodeWithName("ID12", recursively: true)
// 2. set up that node's texture as a SpriteKit scene
let currentImage = nodeToDrawOn.geometry!.firstMaterial!.diffuse.contents as UIImage
skScene = SKScene(size: currentImage.size)
nodeToDrawOn.geometry!.firstMaterial!.diffuse.contents = skScene
// 3. put the currentImage into a background sprite for the skScene
let background = SKSpriteNode(texture: SKTexture(image: currentImage))
background.position = CGPoint(x: skScene.frame.midX, y: skScene.frame.midY)
skScene.addChild(background)
}
@IBAction func tap(sender: UITapGestureRecognizer) {
let results = my3dView.hitTest(sender.locationInView(my3dView), options: [SCNHitTestFirstFoundOnlyKey: true]) as [SCNHitTestResult]
if let result = results.first {
if result.node === nodeToDrawOn {
// 1. get the texture coordinates
let channel = nodeToDrawOn.geometry!.firstMaterial!.diffuse.mappingChannel
let texcoord = result.textureCoordinatesWithMappingChannel(channel)
// 2. place a sprite there
let sprite = SKSpriteNode(color: SKColor.greenColor(), size: CGSize(width: 10, height: 10))
// scale coords: texcoords go 0.0-1.0, skScene space is is pixels
sprite.position.x = texcoord.x * skScene.size.width
sprite.position.y = texcoord.y * skScene.size.height
skScene.addChild(sprite)
}
}
}
는 WWDC14에서 SceneKit State of the Union Demo 참조. SphereKit 장면이 토러스의 텍스처 맵으로 사용되어 페인트 구가 던져진 상태입니다. 구가 토러스와 충돌 할 때마다 SCNHitTestResult
이 생기고 그 텍스쳐를 사용하여 SpriteKit 장면에 페인트 튄자를 만듭니다.
마지막으로, 코드에 대한 몇 가지 스위프트 스타일의 주석 (질문과 대답 무관) :
- 사용
let
대신 var
는 어디든지 당신이 값을 다시 할당 할 필요가 없습니다, 및 최적화 코드를 더 빨리 만들 수 있습니다.
- 명시 적 형식 주석 (
res: SCNHitTestResult
)은 거의 필요하지 않습니다.
- 스위프트 사전은
NSDictionary
에 연결되므로 NSDictionary
을 사용하는 API로 직접 전달할 수 있습니다.
- 신속한 입력 배열 (
hitTest(...) as [SCNHitTestResult]
)로 전송하면 내용을 캐스팅하지 않아도됩니다.
Thx! 나는 매핑 채널을 위해 항상 -1을 얻고있다. – Philsen
테스트에서 0이 표시됩니다. 'SKScene'을 확산 머티리얼로 지정하기 전이나 후에'mappingChannel' 속성을 읽으십니까? 텍스처 좌표가있는 지오메트리를 사용하고 있습니까? – rickster
아니, 나중에 해. 어떻게 기하학이 텍스처 좌표를 가지고 있는지를 결정할 수 있습니다. – Philsen