Unity의 공간 매핑

공간 매핑을 사용하면 HoloLens 디바이스 주위의 전 세계 표면을 나타내는 삼각형 메시를 검색할 수 있습니다. 배치, 폐색 및 공간 분석에 표면 데이터를 사용하여 Unity 프로젝트에 추가 몰입을 제공할 수 있습니다.

Unity에는 다음과 같은 방법으로 개발자에게 노출되는 공간 매핑에 대한 전체 지원이 포함되어 있습니다.

  1. MixedRealityToolkit에서 사용할 수 있는 공간 매핑 구성 요소로, 공간 매핑을 시작하기 위한 편리하고 빠른 경로를 제공합니다.
  2. 모든 권한을 제공하고 보다 정교한 애플리케이션별 사용자 지정을 가능하게 하는 하위 수준 공간 매핑 API

앱에서 공간 매핑을 사용하려면 AppxManifest에서 SpatialPerception 기능을 설정해야 합니다.

디바이스 지원

기능 HoloLens(1세대) HoloLens 2 몰입형 헤드셋
공간 매핑 ✔️ ✔️

SpatialPerception 기능 설정

앱이 공간 매핑 데이터를 사용하려면 SpatialPerception 기능을 사용하도록 설정해야 합니다.

SpatialPerception 기능을 사용하도록 설정하는 방법:

  1. Unity 편집기에서 "플레이어 설정" 창을 엽니다(Project 설정 > 플레이어 편집).
  2. "Windows Store" 탭에서 를 선택합니다.
  3. "게시 설정"를 확장하고 "기능" 목록에서 "SpatialPerception" 기능을 확인합니다.

참고

Unity 프로젝트를 Visual Studio 솔루션으로 이미 내보낸 경우 새 폴더로 내보내거나 Visual Studio AppxManifest에서 이 기능을수동으로 설정해야 합니다.

공간 매핑에는 10.0.10586.0 이상의 MaxVersionTested가 필요합니다.

  1. Visual Studio 솔루션 탐색기 Package.appxmanifest를 마우스 오른쪽 단추로 클릭하고 코드 보기를 선택합니다.
  2. TargetDeviceFamily를 지정하는 줄을 찾고 MaxVersionTested="10.0.10240.0"을MaxVersionTested="10.0.10586.0"으로 변경합니다.
  3. Package.appxmanifest를 저장합니다.

Unity에서 매핑을 추가하는 방법

공간 인식 시스템

MRTK에서 다양한 공간 메시 관찰자 설정에 대한 자세한 내용은 공간 인식 시작 가이드를 참조하세요.

디바이스 내 관찰자에 대한 자세한 내용은 디바이스에 대한 메시 관찰자 구성 가이드를 참조하세요.

장면 이해 관찰자에 대한 자세한 내용은 장면 이해 관찰자 가이드를 참조하세요.

상위 수준 메시 분석: 공간 이해

주의

Spatial Understanding은 Scene Understanding을 위해 더 이상 사용되지 않습니다.

MixedRealityToolkit는 Unity의 홀로그램 API를 기반으로 하는 홀로그램 개발을 위한 유틸리티 코드 컬렉션입니다.

공간 이해

실제 세계에 홀로그램을 배치하는 경우 공간 매핑의 메시 및 표면 평면을 벗어나는 것이 바람직한 경우가 많습니다. 배치가 절차적으로 수행되면 더 높은 수준의 환경 이해가 바람직합니다. 이를 위해서는 일반적으로 바닥, 상한 및 벽이 무엇인지 결정해야 합니다. 또한 배치 제약 조건 집합에 대해 최적화하여 홀로그램 개체에 가장 적합한 물리적 위치를 결정할 수 있습니다.

Young Conker 및 Fragments를 개발하는 동안 Asobo Studios는 방 해결기 개발로 이 문제에 직면했습니다. 이러한 각 게임에는 게임 관련 요구 사항이 있지만 공유 되는 핵심 공간을 이해 하는 기술이 있습니다. HoloToolkit SpatialUnderstanding 라이브러리는이 기술을 캡슐화 하 여 벽에서 빈 공간을 신속 하 게 찾고, 최대값에 개체를 배치 하 고, 문자를 놓을 수 있는 개체를 배치 하 고, 수많은 기타 공간을 이해 하는 쿼리를 수행할 수 있습니다.

모든 소스 코드가 포함 되어 있으므로 요구 사항에 맞게 사용자 지정 하 고 커뮤니티의 개선 사항을 공유할 수 있습니다. C + + 해 찾기에 대 한 코드는 UWP dll로 래핑되어 MixedRealityToolkit 내에 포함 된 prefab의 drop을 사용 하 여 Unity에 노출 되었습니다.

모듈 이해

모듈에 의해 노출 되는 세 가지 기본 인터페이스에는 단순 화면 및 공간 쿼리를 위한 토폴로지, 개체 검색을 위한 모양, 개체 집합의 제약 조건 기반 배치를 위한 개체 배치 해 찾기가 있습니다. 아래에서는 이러한 각 방법에 대해 설명합니다. 세 가지 기본 모듈 인터페이스 외에도, 광선 캐스팅 인터페이스를 사용 하 여 태그가 지정 된 서피스 형식을 검색 하 고 사용자 지정 watertight playspace 메시를 복사할 수 있습니다.

광선 캐스팅

방 검색을 완료 한 후에는 층, 천장 및 벽 같은 표면에 대 한 레이블이 내부적으로 생성 됩니다. 함수는 광선이 PlayspaceRaycast 알려진 표면과 충돌 하는 경우를 반환 하 고, 해당 하는 경우의 형태로 해당 화면에 대 한 정보를 반환 합니다 RaycastResult .

struct RaycastResult
{
    enum SurfaceTypes
    {
        Invalid,    // No intersection
        Other,
        Floor,
        FloorLike,  // Not part of the floor topology,
                    //  but close to the floor and looks like the floor
        Platform,   // Horizontal platform between the ground and
                    //  the ceiling
        Ceiling,
        WallExternal,
        WallLike,   // Not part of the external wall surface,
                    //  but vertical surface that looks like a
                    //  wall structure
    };
    SurfaceTypes SurfaceType;
    float SurfaceArea;  // Zero if unknown
                        //  (i.e. if not part of the topology analysis)
    DirectX::XMFLOAT3 IntersectPoint;
    DirectX::XMFLOAT3 IntersectNormal;
};

내부적으로 raycast는 playspace의 계산 된 8 센티미터 제곱 voxel 표현에 대해 계산 됩니다. 각 voxel에는 처리 된 토폴로지 데이터 (즉, surfels)를 포함 하는 surface 요소 집합이 포함 되어 있습니다. 교차 된 voxel 셀에 포함 된 surfels는 토폴로지 정보를 조회 하는 데 사용 되는 가장 일치 하는 항목과 비교 됩니다. 이 토폴로지 데이터에는 "SurfaceTypes" 열거형의 형식으로 반환 된 레이블 및 교차 된 표면의 노출 영역이 포함 됩니다.

Unity 샘플에서 커서는 각 프레임을 비춥니다. 먼저, Unity의 colliders에 대해 합니다. 두 번째는 모듈의 세계 표현에 대해 이해 합니다. 마지막으로 UI 요소를 다시 한 번 더 합니다. 이 응용 프로그램에서 UI는 우선 순위, 그 다음으로 이해 결과, 마지막으로 Unity의 colliders를 가져옵니다. SurfaceType은 커서 옆에 텍스트로 보고 됩니다.

표면 형식의 레이블이 커서 옆에 표시 됩니다.
표면 형식의 레이블이 커서 옆에 표시 됩니다.

토폴로지 쿼리

DLL 내에서 토폴로지 관리자는 환경의 레이블 지정을 처리 합니다. 위에서 언급 한 것 처럼 대부분의 데이터는 voxel 볼륨 내에 포함 된 surfels 내에 저장 됩니다. 또한 "PlaySpaceInfos" 구조체를 사용 하 여 전 세계 맞춤 (아래에 자세히 설명), 층 및 천장 높이를 포함 하 여 playspace에 대 한 정보를 저장 합니다. 추론은 바닥, 천장 및 벽을 결정 하는 데 사용 됩니다. 예를 들어 1-m2 노출 영역을 포함 하는 가장 크거나 가장 작은 가로 표면은 바닥으로 간주 됩니다.

참고

검색 프로세스 중에 카메라 경로도이 프로세스에서 사용 됩니다.

토폴로지 관리자에 의해 노출 되는 쿼리의 하위 집합은 dll을 통해 노출 됩니다. 노출 된 토폴로지 쿼리는 다음과 같습니다.

QueryTopology_FindPositionsOnWalls
QueryTopology_FindLargePositionsOnWalls
QueryTopology_FindLargestWall
QueryTopology_FindPositionsOnFloor
QueryTopology_FindLargestPositionsOnFloor
QueryTopology_FindPositionsSittable

각 쿼리에는 쿼리 유형과 관련 된 매개 변수 집합이 있습니다. 다음 예에서는 사용자가 & 원하는 볼륨의 최소 높이 너비, 바닥의 최소 배치 높이 및 볼륨 앞의 최소 여유 공간을 지정 합니다. 모든 측정이 미터 단위입니다.

EXTERN_C __declspec(dllexport) int QueryTopology_FindPositionsOnWalls(
    _In_ float minHeightOfWallSpace,
    _In_ float minWidthOfWallSpace,
    _In_ float minHeightAboveFloor,
    _In_ float minFacingClearance,
    _In_ int locationCount,
    _Inout_ Dll_Interface::TopologyResult* locationData)

이러한 각 쿼리는 미리 할당 된 "TopologyResult" 구조체 배열을 사용 합니다. "LocationCount" 매개 변수는 전달 된 배열의 길이를 지정 합니다. 반환 값은 반환 된 위치 수를 보고 합니다. 이 숫자는 전달 된 "locationCount" 매개 변수 보다 크지 않습니다.

"TopologyResult"에는 반환 된 볼륨의 중심 위치, 방향 (예: 일반) 및 찾은 공간의 크기가 포함 됩니다.

struct TopologyResult
{
    DirectX::XMFLOAT3 position;
    DirectX::XMFLOAT3 normal;
    float width;
    float length;
};

참고

Unity 샘플에서 이러한 각 쿼리는 가상 UI 패널의 단추에 연결 됩니다. 샘플에서는 이러한 각 쿼리에 대 한 매개 변수를 적절 한 값으로 하드 코드 합니다. 더 많은 예제는 샘플 코드의 SpaceVisualizer를 참조 하세요.

셰이프 쿼리

Dll에서 shape analyzer ("ShapeAnalyzer_W")는 토폴로지 분석기를 사용 하 여 사용자가 정의한 사용자 지정 셰이프와 일치 시킵니다. Unity 샘플은 셰이프 집합을 정의 하 고 셰이프 탭 내의 앱 내 쿼리 메뉴를 통해 결과를 제공 합니다. 사용자는 자신의 개체 셰이프 쿼리를 정의 하 고 응용 프로그램에 필요한 대로 해당 쿼리를 사용할 수 있습니다.

셰이프 분석은 가로 표면 에서만 작동 합니다. 예를 들어, 소파는 평평한 좌석 표면 및 소파 위쪽의 평면에 의해 정의 됩니다. 셰이프 쿼리는 두 개의 서피스가 정렬 되 고 연결 된 특정 크기, 높이 및 가로 세로 막대의 두 표면을 찾습니다. Api 용어를 사용 하 여 소파와 후면 위쪽은 셰이프 구성 요소 이며 맞춤 요구 사항은 셰이프 구성 요소 제약 조건입니다.

Unity 샘플 (ShapeDefinition)에 정의 된 "sittable" 개체에 대 한 예제 쿼리는 다음과 같습니다.

shapeComponents = new List<ShapeComponent>()
{
    new ShapeComponent(
        new List<ShapeComponentConstraint>()
        {
            ShapeComponentConstraint.Create_SurfaceHeight_Between(0.2f, 0.6f),
            ShapeComponentConstraint.Create_SurfaceCount_Min(1),
            ShapeComponentConstraint.Create_SurfaceArea_Min(0.035f),
        }
    ),
};
AddShape("Sittable", shapeComponents);

각 셰이프 쿼리는 각각 구성 요소 제약 조건 집합과 구성 요소 간의 종속성을 나열 하는 셰이프 제약 조건 집합을 포함 하는 셰이프 구성 요소 집합으로 정의 됩니다. 이 예에는 단일 구성 요소 정의에 세 개의 제약 조건이 포함 되 고 구성 요소 간의 모양 제약 조건 (구성 요소 하나만 있는 경우)이 포함 되지 않습니다.

이와 대조적으로, 소파 셰이프에는 두 개의 셰이프 구성 요소와 4 개의 셰이프 제약 조건이 있습니다. 구성 요소는 사용자의 구성 요소 목록에서 인덱스로 식별 됩니다 (이 예제에서는 0 및 1).

shapeConstraints = new List<ShapeConstraint>()
{
    ShapeConstraint.Create_RectanglesSameLength(0, 1, 0.6f),
    ShapeConstraint.Create_RectanglesParallel(0, 1),
    ShapeConstraint.Create_RectanglesAligned(0, 1, 0.3f),
    ShapeConstraint.Create_AtBackOf(1, 0),
};

래퍼 함수는 사용자 지정 셰이프 정의를 쉽게 만들기 위해 Unity 모듈에서 제공 됩니다. 구성 요소 및 모양 제약 조건의 전체 목록은 "ShapeComponentConstraint"의 "SpatialUnderstandingDll" 및 "ShapeConstraint" 구조체에서 찾을 수 있습니다.

이 화면에서 사각형 모양을 찾았습니다.
이 화면에서 사각형 모양을 찾았습니다.

개체 배치 해 찾기

개체 배치 해결 기를 사용 하 여 개체를 배치할 실제 방에 있는 이상적인 위치를 식별할 수 있습니다. 개체 규칙과 제약 조건이 지정 된 경우 가장 적합 한 위치를 찾을 수 있습니다. 또한 개체 쿼리는 "Solver_RemoveObject" 또는 "Solver_RemoveAllObjects" 호출을 통해 개체가 제거 될 때까지 지속 되어 제한 된 다중 개체 배치를 허용 합니다. 개체 배치 쿼리는 매개 변수가 있는 배치 유형, 규칙 목록 및 제약 조건 목록의 세 부분으로 구성 됩니다. 쿼리를 실행 하려면 다음 API를 사용 합니다.

public static int Solver_PlaceObject(
            [In] string objectName,
            [In] IntPtr placementDefinition,        // ObjectPlacementDefinition
            [In] int placementRuleCount,
            [In] IntPtr placementRules,             // ObjectPlacementRule
            [In] int constraintCount,
            [In] IntPtr placementConstraints,       // ObjectPlacementConstraint
            [Out] IntPtr placementResult)

이 함수는 개체 이름, 배치 정의 및 규칙 및 제약 조건 목록을 사용 합니다. C # 래퍼는 생성 도우미 함수를 제공 하 여 규칙 및 제약 조건 생성을 용이 하 게 합니다. 배치 정의에는 쿼리 유형 즉, 다음 중 하나를 포함 합니다.

public enum PlacementType
{
    Place_OnFloor,
    Place_OnWall,
    Place_OnCeiling,
    Place_OnShape,
    Place_OnEdge,
    Place_OnFloorAndCeiling,
    Place_RandomInAir,
    Place_InMidAir,
    Place_UnderFurnitureEdge,
};

각 배치 형식에는 해당 형식에 고유한 매개 변수 집합이 있습니다. "ObjectPlacementDefinition" 구조체에는 이러한 정의를 만들기 위한 정적 도우미 함수 집합이 포함 되어 있습니다. 예를 들어 바닥에서 개체를 배치할 위치를 찾으려면 다음 함수를 사용할 수 있습니다. 공용 정적 ObjectPlacementDefinition Create_OnFloor (Vector3 halfDims) 배치 유형 외에도 규칙 및 제약 조건 집합을 제공할 수 있습니다. 규칙을 위반할 수 없습니다. 그러면 형식 및 규칙을 충족 하는 가능한 배치 위치가 최적의 배치 위치를 선택 하기 위해 제약 조건 집합에 대해 최적화 됩니다. 제공 된 정적 생성 함수를 통해 각 규칙 및 제약 조건을 만들 수 있습니다. 아래에는 규칙 및 제약 조건 생성 함수 예제가 나와 있습니다.

public static ObjectPlacementRule Create_AwayFromPosition(
    Vector3 position, float minDistance)
public static ObjectPlacementConstraint Create_NearPoint(
    Vector3 position, float minDistance = 0.0f, float maxDistance = 0.0f)

아래 개체 배치 쿼리는 이전에 배치 된 다른 개체와 실내 가운데 근처에서 절반 측정기 큐브를 표면의 가장자리에 배치 하는 위치를 찾고 있습니다.

List<ObjectPlacementRule> rules =
    new List<ObjectPlacementRule>() {
        ObjectPlacementRule.Create_AwayFromOtherObjects(1.0f),
    };

List<ObjectPlacementConstraint> constraints =
    new List<ObjectPlacementConstraint> {
        ObjectPlacementConstraint.Create_NearCenter(),
    };

Solver_PlaceObject(
    “MyCustomObject”,
    new ObjectPlacementDefinition.Create_OnEdge(
        new Vector3(0.25f, 0.25f, 0.25f),
        new Vector3(0.25f, 0.25f, 0.25f)),
    rules.Count,
    UnderstandingDLL.PinObject(rules.ToArray()),
    constraints.Count,
    UnderstandingDLL.PinObject(constraints.ToArray()),
    UnderstandingDLL.GetStaticObjectPlacementResultPtr());

성공 하면 배치 위치, 차원 및 방향을 포함 하는 "ObjectPlacementResult" 구조가 반환 됩니다. 또한 배치가 배치 된 개체의 내부 목록에 추가 됩니다. 이후 배치 쿼리에서는이 개체를 고려 합니다. Unity 샘플의 "LevelSolver 찾기 .cs" 파일에는 더 많은 예제 쿼리가 포함 되어 있습니다.

개체 배치 결과
그림 3: 파란 상자에 카메라 위치 규칙을 사용 하 여 바닥 쿼리를 수행 하는 세 위치의 결과

수준 또는 응용 프로그램 시나리오에 필요한 여러 개체의 배치 위치를 해결 하는 경우에는 먼저 필요에 따라 공간을 찾을 수 있는 확률을 최대화 하기 위해 필수적인 개체와 큼 개체를 해결 합니다. 배치 순서는 중요 합니다. 개체 배치를 찾을 수 없는 경우 제한 된 구성으로 시도 합니다. 여러 방 구성에서 기능을 지원 하려면 대체 (fallback) 구성 집합이 있어야 합니다.

대화방 스캔 프로세스

HoloLens에서 제공 하는 공간 매핑 솔루션은 전체 문제 영역에 대 한 요구 사항을 충족 하기에 충분히 제네릭으로 설계 되었지만 공간 파악 모듈은 두 가지 특정 게임의 요구 사항을 지원 하기 위해 작성 되었습니다. 해당 솔루션은 아래에 요약 된 특정 프로세스 및 가정 집합을 중심으로 구성 됩니다.

Fixed size playspace – The user specifies the maximum playspace size in the init call.

One-time scan process –
    The process requires a discrete scanning phase where the user walks around,
    defining the playspace.
    Query functions will not function until after the scan has been finalized.

사용자 기반 플레이 공간 "그리기"-검사 단계 중에 사용자가 재생 속도를 이동 하 고 표시 하 여 영역을 효과적으로 그려야 합니다. 생성 된 메시는이 단계에서 사용자 의견을 제공 하는 데 중요 합니다. 실내 홈 또는 office 설정 – 쿼리 함수는 직각으로 평면 및 벽 주위에 디자인 됩니다. 소프트 제한입니다. 그러나 검사 단계 중에 주 축 분석을 완료 하 여 주 및 보조 축을 따라 메시 공간 분할을 최적화 합니다. 포함 된 SpatialUnderstanding 파일은 검사 단계 프로세스를 관리 합니다. 다음 함수를 호출 합니다.

SpatialUnderstanding_Init – Called once at the start.

GeneratePlayspace_InitScan – Indicates that the scan phase should begin.

GeneratePlayspace_UpdateScan_DynamicScan –
    Called each frame to update the scanning process. The camera position and
    orientation is passed in and is used for the playspace painting process,
    described above.

GeneratePlayspace_RequestFinish –
    Called to finalize the playspace. This will use the areas “painted” during
    the scan phase to define and lock the playspace. The application can query
    statistics during the scanning phase as well as query the custom mesh for
    providing user feedback.

Import_UnderstandingMesh –
    During scanning, the “SpatialUnderstandingCustomMesh” behavior provided by
    the module and placed on the understanding prefab will periodically query the
    custom mesh generated by the process. In addition, this is done once more
    after scanning has been finalized.

"SpatialUnderstanding" 동작으로 구동 되는 검색 흐름은 InitScan을 호출한 다음 각 프레임을 UpdateScan 합니다. 통계 쿼리가 적절한 검사를 보고하면 사용자는 RequestFinish를 호출하여 검사 단계의 끝을 나타내는 airtap을 할 수 있습니다. UpdateScan은 해당 반환 값이 dll이 처리를 완료했음을 나타내기 전까지 계속 호출됩니다.

메시 이해

이해 dll은 내부적으로 플레이스페이스를 8cm 크기의 복셀 큐브 그리드로 저장합니다. 검사의 초기 부분에서는 기본 구성 요소 분석을 완료하여 방의 축을 확인합니다. 내부적으로 이러한 축에 맞춰진 복셀 공간을 저장합니다. 메시는 복셀 볼륨에서 isosurface를 추출하여 약 1초마다 생성됩니다.

복셀 볼륨에서 생성된 메시 생성
복셀 볼륨에서 생성된 메시 생성

문제 해결

  • SpatialPerception 기능을 설정해야 합니다.
  • 추적이 손실되면 다음 OnSurfaceChanged 이벤트가 모든 메시를 제거합니다.

Mixed Reality Toolkit 공간 매핑

Mixed Reality Toolkit 공간 매핑 사용에 대한 자세한 내용은 MRTK 문서의 공간 인식 섹션을 참조하세요.

다음 개발 검사점

앞에서 설명한 Unity 개발 여정을 따라가는 경우 MRTK 핵심 구성 요소에 대해 알아보세요. 여기에서 다음 구성 요소로 진행할 수 있습니다.

또는 Mixed Reality 플랫폼 기능 및 API로 이동합니다.

언제든지 Unity 개발 검사점으로 돌아갈 수 있습니다.

참조