ARKit Xamarin.iOS에서 UrhoSharp 사용Using ARKit with UrhoSharp in Xamarin.iOS

도입 ARKit, Apple 만들었다 증강된 현실 응용 프로그램을 만드는 개발자를 위한 간단 합니다.With the introduction of ARKit, Apple has made it simple for developers to create augmented reality applications. ARKit 장치의 정확한 위치를 추적 하 고 검색 전 세계의 다양 한 표면 및 코드로 ARKit 전송 되는 데이터를 혼합 하려면 개발자에 게 달려 됩니다.ARKit can track the exact position of your device and detect various surfaces on the world, and it is then up to the developer to blend the data coming out of ARKit into your code.

UrhoSharp 제공 하는 포괄적이 고 사용 하기 쉬운 3D API를 3D 응용 프로그램을 만드는 데 사용할 수 있습니다.UrhoSharp provides a comprehensive and easy to use 3D API that you can use to create 3D applications. 둘 다 수 전 세계에 대 한 실제 정보를 제공 하는 ARKit 및 결과를 렌더링할 Urho 함께 혼합 합니다.Both of these can be blended together, ARKit to provide the physical information about the world, and Urho to render the results.

이 페이지를 증강된 현실 훌륭한 응용 프로그램을 만드는 데이 두 환경을 연결 하는 방법에 설명 합니다.This page explains how to connect these two worlds together to create great augmented reality applications.

기본 사항The Basics

원하는 작업을 수행 하는 iPhone/iPad에서 볼 수 있듯이 전 세계 위에 있는 3D 콘텐츠입니다.What we want to do is present 3D content on top of the world as seen by the iPhone/iPad. 3D 콘텐츠를 사용 하 여 장치의 카메라에서 가져온 내용을 blend는 및 장치의으로 이동할 때 전시실 되도록 룸의 일부인 이러한 이전과 3D 개체-이 환경에 개체를 고정 하면 됩니다.The idea is to blend the contents coming from the device’s camera with the 3D content, and as the user of the device moves around the room to ensure that the 3D object behave as is they part of that room - this is done by anchoring the objects into this world.

ARKit에 애니메이션된 그림

Urho 라이브러리 3D 자산을 로드 하 고 전 세계에서 배치를 사용 하 고 ARKit 카메라 뿐만 아니라 전 세계에서 전화의 위치에서 들어오는 비디오 스트림을 가져오려면 사용 합니다.We will be using the Urho library to load our 3D assets and place them on the world, and we will be using ARKit to get the video stream coming from the camera as well as the location of the phone in the world. 사용자가 자신의 휴대폰을 사용 하 여,는를 사용 하 여 변경 내용을 위치에 Urho 엔진 표시 하는 좌표계를 업데이트 합니다.As the user moves with his phone, we will use the changes in the location to update the coordinate system that the Urho engine is displaying.

이러한 방식으로 3D 공간에서 개체를 배치 하 고 사용자가 이동할 때 3D 개체의 위치 위치 및 배치 된 위치를 반영 합니다.This way, when you place an object in the 3D space and the user moves, the location of the 3D object reflects the place and location where it was placed.

응용 프로그램 설정Setting up your application

iOS 응용 프로그램 시작iOS Application Launch

IOS 응용 프로그램 만들기 및 3D 콘텐츠를 시작, 구현 하는의 서브 클래스를 만들어이 작업을 수행 합니다 Urho.Application 재정의 하 여 설치 코드를 입력 하 고는 Start 메서드.Your iOS application needs to create and launch your 3D content, you do this by creating an implementing a subclass of the Urho.Application and provide your setup code by overriding the Start method. 이 데이터를 이벤트 처리기에 설정 된 장면 가져옵니다 채워집니다.This is where your scene gets populated with data, event handlers are setup and so on.

도입 했습니다를 Urho.ArkitApp 는 클래스 Urho.Application 및 해당 Start 메서드는 주요 작업을 수행 합니다.We have introduced an Urho.ArkitApp class that subclasses Urho.Application and on its Start method does the heavy lifting. 형식의 기본 클래스를 변경 하기만 하면 작업을 수행 하는 응용 프로그램에 기존 Urho Urho.ArkitApp urho 장면에 전 세계에서 실행 하는 응용 프로그램에 있습니다.All you need to do to your existing Urho application is change the base class to be of type Urho.ArkitApp and you have an application that will run your urho Scene in the world.

ArkitApp 클래스The ArkitApp Class

편리한 기본값, 일부 키 개체를 사용 하 여 두 장면 집합 뿐만 아니라 ARKit 이벤트를 처리 하는 운영 체제에서 배달 하는 대로이 클래스를 제공 합니다.This class provides a set of convenient defaults, both a scene with some key objects as well as the processing of ARKit events as they are delivered by the operating system.

설치 프로그램 수행 된 Start 가상 메서드.The setup takes place in the Start virtual method. 사용 하 여 부모 체인에 있는지 확인 해야 하는 서브 클래스에서이 메서드를 재정의 하는 경우 base.Start() 구현에 따라 고유 합니다.When you override this method on your subclass, you need to make sure to chain to your parent by using base.Start() on your own implementation.

Start 메서드 장면, 뷰포트, 카메라 및 방향성을 설정 하 고 공용 속성으로 표시 합니다.The Start method sets up the scene, viewport, camera and a directional light, and surfaces those as public properties:

  • Scene 개체를 저장 하려면a Scene to hold your objects,
  • 방향 Light 그림자 및 해당 위치를 통해 사용할 수는 LightNode 속성a directional Light with shadows, and whose location is available via the LightNode property
  • Camera ARKit 응용 프로그램에 대 한 업데이트를 제공 하는 경우 해당 구성 요소 업데이트 되 고a Camera whose components are updated when ARKit delivers an update to the application and
  • ViewPort 결과 표시 합니다.a ViewPort displaying the results.

코드Your code

서브 클래스 해야 합니다 ArkitApp 클래스를 재정의 합니다 Start 메서드.You then need to subclass the ArkitApp class and override the Start method. 먼저 방법을 수행 해야 하는 체인이 최대 합니다 ArkitApp.Start 호출 하 여 base.Start()입니다.The first thing that your method should do is chain up to the ArkitApp.Start by calling base.Start(). 그 후 장면에 개체를 추가, 광원, 어두운 영역 또는 이벤트를 처리 하려면 사용자 지정 하 여 ArkitApp 속성 설정을 사용할 수 있습니다.After that, you can use any of the properties setup by ArkitApp to add your objects to the scene, customize the lights, shadows or events that you want to handle.

질감을 사용 하 여 애니메이션된 된 문자를 로드 하 고 다음 구현으로 애니메이션을 재생 하는 ARKit/UrhoSharp 샘플:The ARKit/UrhoSharp sample loads an animated character with textures and plays the animation, with the following implementation:

```csharp
public class MutantDemo : ArkitApp
{
    [Preserve]
    public MutantDemo(ApplicationOptions opts) : base(opts) { }

    Node mutantNode;

    protected override void Start()
    {
        base.Start ();

        // Mutant
        mutantNode = Scene.CreateChild();
        mutantNode.Rotation = new Quaternion(x: 0, y:15, z:0);
        mutantNode.Position = new Vector3(0, -1f, 2f); /*two meters away*/
        mutantNode.SetScale(0.5f);

        var mutant = mutantNode.CreateComponent<AnimatedModel>();
        mutant.Model = ResourceCache.GetModel("Models/Mutant.mdl");
        mutant.Material = ResourceCache.GetMaterial("Materials/mutant_M.xml");

        var animation = mutantNode.CreateComponent<AnimationController>();
        animation.Play("Animations/Mutant_HipHop1.ani", 0, true, 0.2f);
    }
}
```

실제로 3D 콘텐츠 확대 된 현실에 표시 하도록이 시점에서 수행 해야 하는 모든 하며And that is really all that you have to do at this point to have your 3D content displayed in augmented reality.

Urho 자산이이 형식으로 내보낼 필요 하므로 애니메이션 및 3D 모델에 대 한 사용자 지정 형식을 사용 합니다.Urho uses custom formats for 3D models and animations, so you need to export your assets into this format. 와 같은 도구를 사용할 수는 Urho3D Blender add-inUrhoAssetImporter Urho에 필요한 형식으로 3D 최대 DAE, DBX, OBJ, Blend와 같은 인기 있는 형식에서 이러한 자산을 변환할 수 있는 합니다.You can use tools like the Urho3D Blender Add-in and UrhoAssetImporter that can convert these assets from popular formats like DBX, DAE, OBJ, Blend, 3D-Max into the format required by Urho.

Urho를 사용 하 여 3D 응용 프로그램 만들기에 대 한 자세한 내용은 참조는 UrhoSharp 소개 가이드입니다.To learn more about creating 3D applications using Urho, visit the Introduction to UrhoSharp guide.

ArkitApp 방어ArkitApp in Depth

참고

이 섹션에서는 UrhoSharp 및 ARKit 기본 환경을 사용자 지정 하거나 통합의 작동 방식에 대해 깊이 이해 하는 개발자를 위한 것입니다.This section is intended for developers that want to customize the default experience of UrhoSharp and ARKit or want to get a deeper insight on how the integration works. 이 섹션을 참조 하는 데 필요한 것입니다.It is not necessary to read this section.

ARKit API는 상당히 간단, 만들기 및 구성 하는 ARSession 하는 개체를 제공 하기 시작 ARFrame 개체입니다.The ARKit API is pretty simple, you create and configure an ARSession object which then start delivering ARFrame objects. 여기에 예상 되는 실제 위치가 장치 뿐만 아니라 카메라에서 캡처된 이미지 모두 포함 되어 있습니다.These contain both the image captured by the camera as well as the estimated real-world position of the device.

수 카메라에서 3D 콘텐츠를 사용 하 여 우리에 게 제공 되는 이미지를 작성 하 고 장치 위치와 위치 가능성에 맞게 UrhoSharp 카메라를 조정 합니다.We will be composing the images being delivered by the camera to us with our 3D content, and adjust the camera in UrhoSharp to match the chances in the device location and position.

다음 다이어그램에서는 일어나는 무엇을 ArkitApp 클래스:The following diagram shows what is taking place in the ArkitApp class:

클래스 및 화면을 ArkitApp에서의 다이어그램Diagram of classes and screens in the ArkitApp

프레임을 렌더링합니다.Rendering the Frames

아이디어는 간단 하, 결합 된 이미지를 생성 하는 3D 그래픽을 사용 하 여 카메라에서 들어오는 비디오를 결합 합니다.The idea is simple, combine the video coming out of the camera with our 3D graphics to produce the combined image. 에서는 됩니다 수 일련의 이러한 캡처된 이미지 순서 대로 가져오고 Urho 장면으로이 입력을 혼합 됩니다 것입니다.We will be getting a series of these captured images in sequence, and we will mix this input with the Urho scene.

작업을 수행 하는 가장 간단한 방법은 삽입 하는 것을 RenderPathCommand 를 주 RenderPath 합니다.The simplest way to do it is to insert a RenderPathCommand into the main RenderPath. 단일 프레임을 그리려면 수행 되는 명령의 집합입니다.This is a set of commands that are performed to draw a single frame. 이 명령에 전달 하는 모든 질감으로 뷰포트를 채워집니다.This command will fill the viewport with any texture we pass to it. 에서는이 프로세스는 첫 번째 프레임에 설정과 실제 정의에서 수행 됩니다 ARRenderPath.xml 이 시점에서 로드 되는 파일입니다.We set this up on the first frame that is process, and the actual definition is done in th ARRenderPath.xml file that is loaded at this point.

그러나이 두 환경을 함께 혼합 하려면 두 가지 문제를 사용 하 여 직면 했습니다.However, we are faced with two problems to blend these two worlds together:

  1. IOS에서 GPU 질감은 2의 제곱이 해상도 있어야 없는 카메라에서 얻게 되는 프레임 예를 들어 2의 거듭제곱 된 해결 방법: 1280x720.On iOS, GPU Textures must have a resolution that is a power of two, but the frames that we will get from the camera do not have resolution that are a power of two, for example: 1280x720.
  2. 프레임은 인코딩된 YUV 두 이미지-하 고 색도 광도가 됩니다 나타내는 형식입니다.The frames are encoded in YUV format, represented by two images - luma and chroma.

YUV 프레임을 두 개의 다른 해결 방법으로 제공 됩니다.The YUV frames come in two different resolutions. 광도 (기본적으로 회색조 이미지)를 나타내며 훨씬 더 작은 640x360 색차 구성 요소를 1280 x 720 이미지:a 1280x720 image representing luminance (basically a gray scale image) and much smaller 640x360 for the chrominance component:

Y 결합 및 UV 구성 요소를 보여 주는 이미지

OpenGL ES를 사용 하 여 전체 색이 지정 된 이미지를 그릴 텍스처 슬롯에서 광도 (Y 구성 요소) 및 색차 (UV 평면)를 사용 하는 작은 셰이더를 작성 해야 합니다.To draw a full colored image using OpenGL ES we have to write a small shader that takes luminance (Y component) and chrominance (UV planes) from the texture slots. UrhoSharp에서 이름이-"sDiffMap" 및 "sNormalMap" 하며 RGB 형식으로 변환:In UrhoSharp they have names - “sDiffMap” and “sNormalMap” and convert them into RGB format:

mat4 ycbcrToRGBTransform = mat4(
    vec4(+1.0000, +1.0000, +1.0000, +0.0000),
    vec4(+0.0000, -0.3441, +1.7720, +0.0000),
    vec4(+1.4020, -0.7141, +0.0000, +0.0000),
    vec4(-0.7010, +0.5291, -0.8860, +1.0000));

vec4 ycbcr = vec4(texture2D(sDiffMap, vTexCoord).r,
                    texture2D(sNormalMap, vTexCoord).ra, 1.0);
gl_FragColor = ycbcrToRGBTransform * ycbcr;

두 확인 활용 되지 않은 텍스처를 렌더링 하 Texture2D 다음 매개 변수를 사용 하 여 정의 해야 합니다.To render the texture that does not have a power of two resolution we have to define Texture2D with the following parameters:

// texture for UV-plane;
cameraUVtexture = new Texture2D();
cameraUVtexture.SetNumLevels(1);
cameraUVtexture.SetSize(640, 360, Graphics.LuminanceAlphaFormat, TextureUsage.Dynamic);
cameraUVtexture.FilterMode = TextureFilterMode.Bilinear;
cameraUVtexture.SetAddressMode(TextureCoordinate.U, TextureAddressMode.Clamp);
cameraUVtexture.SetAddressMode(TextureCoordinate.V, TextureAddressMode.Clamp);

따라서 배경으로 캡처된 이미지를 렌더링 하 고 같은 scary 뮤턴트 모든 장면 위에 렌더링할 수 있습니다.Thus we are able to render captured images as a background and render any scene above it like that scary mutant.

카메라를 조정합니다.Adjusting the Camera

ARFrame 개체도 예상된 장치 위치를 포함 합니다.The ARFrame objects also contain the estimated device position. 게임 카메라 ARFrame 이동 해야-ARKit 전에 없었습니다 하 추적 장치 방향 (롤포워드, 피치 및 요) 비디오 위에 고정된 홀로그램 렌더링-하며 장치를 조금 이동 하는 경우-그리 홀로그램 이제 드리프트 됩니다.We now we need to move game camera ARFrame - before ARKit it was not a big deal to track device orientation (roll, pitch and yaw) and render a pinned hologram on top of the video - but if you move your device a bit - holograms will drift.

자이로스코프가 같은 내장 센서 이동을 추적할 수 없기 때문에 이런, 가속만 할 수 있습니다.That happens because built-in sensors such as gyroscope are not able to track movements, they can only acceleration. ARKit 분석 각 프레임 및 추출 기능 지점은 추적 되며 따라서 수를 정확 하 게 제공 하는 데이터 이동 및 회전 포함 된 행렬을 변환 합니다.ARKit analyses each frame and extracts feature points to track and thus is able to give us an accurate Transform matrix containing movement and rotation data.

이 예를 들어 방법에서는 현재 위치를 가져올 수 있습니다.For example, this is how we can obtain current position:

var row = arCamera.Transform.Row3;
CameraNode.Position = new Vector3(row.X, row.Y, -row.Z);

사용 하 여 -row.Z ARKit 오른손 좌표계를 사용 하기 때문에 있습니다.We use -row.Z because ARKit uses a right-handed coordinate system.

평면 검색Plane detection

ARKit는 가로 평면을 검색할 수 있습니다 하 고이 기능을 사용 하면 실제 세계와 상호 작용할 수 있습니다, 그리고 예를 들어, 실제 테이블 또는 층을 뮤턴트를 지정할 수 있습니다.ARKit is able to detect horizontal planes and this ability allows you to interact with the real world, for example, we can place the mutant on a real table or a floor. 작업을 수행 하는 가장 간단한 방법은 HitTest 메서드 (플레이어가)를 사용 하는 것입니다.The simplest way to do that is to use HitTest method (raycasting). 화면 좌표로 변환 (0.5, 0.5 중앙) 실제 좌표를 (0, 0 0은 첫 번째 프레임의 위치).It converts screen coordinates (0.5;0.5 is the center) into the real world coordinates (0;0;0 is the first frame's location).

protected Vector3? HitTest(float screenX = 0.5f, float screenY = 0.5f)
{
    var result = ARSession.CurrentFrame.HitTest(new CGPoint(screenX, screenY),
        ARHitTestResultType.ExistingPlaneUsingExtent)?.FirstOrDefault();
    if (result != null)
    {
        var row = result.WorldTransform.Row3;
        return new Vector3(row.X, row.Y, -row.Z);
    }
    return null;
}

이제 탭에서는 장치 화면에서 위치에 따라 가로 화면에서를 뮤턴트를 지정할 수 있습니다.now we can place the mutant on a horizontal surface depending on where on the device screen we tap:

void OnTouchEnd(TouchEndEventArgs e)
{
    float x = e.X / (float)Graphics.Width;
    float y = e.Y / (float)Graphics.Height;
    var pos = HitTest(x, y);
    if (pos != null)
    mutantNode.Position = pos.Value;
}

보기 이동으로 변경 하는 애니메이션된 그림 평면

사실적 조명Realistic lighting

실제 조명 조건에 따라 더 밝게 또는 주변에 더 잘 맞게 음영이 짙을 수록 가상 장면 이어야 합니다.Depending on the real world lighting conditions, the virtual scene should be lighter or darker to better match its surroundings. Urho 앰비언트 조명 조정에 사용할 수 있는 LightEstimate 속성을 포함 하는 ARFrame 이렇게 같이:ARFrame contains a LightEstimate property that we can use to adjust the Urho ambient light, this is done like this:

var ambientIntensity = (float) frame.LightEstimate.AmbientIntensity / 1000f;
var zone = Scene.GetComponent<Zone>();
zone.AmbientColor = Color.White * ambientIntensity;

IOS-HoloLens 초과Beyond iOS - HoloLens

UrhoSharp 모든 주요 운영 체제에서 실행이므로 다른 곳에서 기존 코드를 다시 사용할 수 있습니다.UrhoSharp runs on all major operating systems, so you can reuse your existing code elsewhere.

HoloLens에서 실행 하는 가장 흥미로운 플랫폼 중 하나입니다.HoloLens is one of the most exciting platforms it runs on. 즉, 있습니다 iOS과 UrhoSharp 사용 되는 멋진 증강 현실 응용 프로그램을 빌드하는 HoloLens 간을 쉽게 전환할 수 있습니다.This means that you can easily switch between iOS and HoloLens to build awesome Augmented Reality applications using UrhoSharp.

MutantDemo 원본에서 찾을 수 있습니다 github.com/EgorBo/ARKitXamarinDemo합니다.You can find the MutantDemo source at github.com/EgorBo/ARKitXamarinDemo.