unprojectPoint
은 많은 그래픽 지향 라이브러리 (예 : DirectX, 구식 OpenGL, Three.js 등)에서 볼 수있는 것과 유사한 매트릭스 연산 기능입니다. SceneKit에서는 뷰의 메소드로 제공됩니다. 즉, 모델/뷰/프로젝션 행렬 및 뷰가 현재 렌더링에 사용하는 뷰포트를 사용하여 작동합니다. 그러나 그 기능이 어떻게 작동하는지 알면 직접 구현할 수 있습니다.
변환 뷰포트 좌표 (픽셀)를, 클립 공간 좌표계 (사방 1.0 -1.0)
Unproject 함수는 일반적으로 두 가지 일을한다.
클립 공간에서 임의의 Z 값을 가정하고 투영 변환을 반전하고 뷰 (카메라)를 3D 공간 좌표로 변환합니다.
우리는 우리 자신의 기능을 만들 수 있습니다. (경고 : 안된.)
이제
func unproject(screenPoint: float3, // see below for Z depth hint discussion
modelView: float4x4,
projection: float4x4,
viewport: CGRect) -> float3 {
// viewport to clip: subtract viewport origin, divide by size,
// scale/offset from 0...1 to -1...1 coordinate space
let clip = (screenPoint - float3(viewport.x, viewport.y, 1.0))
/float3(viewport.width, viewport.height, 1.0)
* float3(2) - float3(1)
// apply the reverse of the model-view-projection transform
let inversePM = (projection * modelView).inverse
let result = inversePM * float4(clip.x, clip.y, clip.z, 1.0)
return float3(result.x, result.y, result.z)/result.w // perspective divide
}
,이 함수에 전달하는 modelView
행렬 ARCamera.transform
의 역입니다 ... 그것을 사용하는, 당신은 또한 ARCamera
에서 직접 projectionMatrix
를 얻을 수 있습니다. 따라서 한 시점에서 2D 위치를 잡는 경우 카메라 매트릭스를 잡고 그 시간에 3D로 뒤로 작업 할 수 있습니다.
내가 언급 한 "Z 깊이 힌트"의 문제가 여전히 있습니다. 렌더러가 3D에서 2D로 투영 할 때 정보가 손실됩니다 (실제 그 중 하나 인 D). 따라서 다시 3D로 변환 할 때 정보를 복구하거나 추측해야합니다. 위의 함수에 전달하는 screenPoint
은 x 및 y 픽셀 좌표에 0과 1 사이의 심도 값을 더한 값입니다. 0은 카메라에 더 가깝고 1 더 멀리있다. 당신이 알고리즘의 나머지 부분을 어떻게 설계하는지에 달려 있습니다. (적어도 Z = 0과 Z = 1을 모두 해제 할 수 있습니다. 원래 지점 어딘가에 그 라인을 따라이있는 3D에서 선분의 끝점을 얻을 수 있습니다.)
물론, 이것이 참으로 소설 CNN 기반 접근법과 함께 할 수 있는지 여부가 전적으로 다른 질문입니다. 그러나 적어도 당신은 유용한 3D 그래픽 수학을 배웠습니다!