MRが楽しい

MRやVRについて学習したことを書き残す

HoloLensでカメラ画像を取得する その3(キャプチャ画像をテクスチャへ反映する)

本日は Unity の技術調査枠です。
先日の資料を基に、キャプチャ画像をテクスチャへ反映するプロジェクトを作成します。
bluebirdofoz.hatenablog.com

前回ドキュメントに基づいて、次はキャプチャ画像をテクスチャへ反映する動作を実装します。
プロジェクトに以下の Panel を追加しました。
f:id:bluebirdofoz:20180318070433j:plain

AirTap時に撮影を行い、画像をテクスチャとして Panel のマテリアルに反映します。。
・CaptureTest.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using HoloToolkit.Unity.InputModule;
using System;
using System.IO;
using System.Linq;
using UnityEngine.XR.WSA.WebCam;

public class CaptureTest : MonoBehaviour, IInputClickHandler
{
    public GameObject targetObject = null;
    public Material formatMaterial = null;
    
    private PhotoCapture photoCaptureObject = null;
    private Material changeMaterial = null;
    // Use this for initialization
    void Start()
    {
        // AirTap時のイベントを設定する
        InputManager.Instance.PushFallbackInputHandler(gameObject);
    }

    void OnPhotoCaptureCreated(PhotoCapture captureObject)
    {
        Debug.Log("OnPhotoCaptureCreated");
        photoCaptureObject = captureObject;

        Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();

        CameraParameters c = new CameraParameters();
        c.hologramOpacity = 0.0f;
        c.cameraResolutionWidth = cameraResolution.width;
        c.cameraResolutionHeight = cameraResolution.height;
        c.pixelFormat = CapturePixelFormat.BGRA32;

        captureObject.StartPhotoModeAsync(c, OnPhotoModeStarted);
    }

    void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
    {
        Debug.Log("OnStoppedPhotoMode");
        photoCaptureObject.Dispose();
        photoCaptureObject = null;
    }

    private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
    {
        Debug.Log("OnPhotoModeStarted");
        if (result.success)
        {
            Debug.Log("OnPhotoModeStarted: success");
            photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
        }
        else
        {
            Debug.LogError("OnPhotoModeStarted: Unable to start photo mode!");
        }
    }

    void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
    {
        Debug.Log("OnCapturedPhotoToMemory");
        if (result.success)
        {
            Debug.Log("OnCapturedPhotoToMemory: success");
            // 使用するTexture2Dを作成し、正しい解像度を設定する
            // Create our Texture2D for use and set the correct resolution
            Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
            Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
            // 画像データをターゲットテクスチャにコピーする
            // Copy the raw image data into our target texture
            photoCaptureFrame.UploadImageDataToTexture(targetTexture);
            // テクスチャをマテリアルに適用する
            changeMaterial = new Material(formatMaterial);
            changeMaterial.SetTexture("_MainTex", targetTexture);
            targetObject.GetComponent<Image>().material = changeMaterial;
        }
        // クリーンアップ
        // Clean up
        photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
    }

    /// <summary>
    /// クリックイベント
    /// </summary>
    public void OnInputClicked(InputClickedEventData eventData)
    {
        Debug.Log("capture");
        // キャプチャを開始する
        PhotoCapture.CreateAsync(true, OnPhotoCaptureCreated);
    }

    // Update is called once per frame
    void Update()
    {
    }
}

上記スクリプトをプロジェクト内のゲームオブジェクトにアタッチします。
f:id:bluebirdofoz:20180318070519j:plain

因みにフォーマットマテリアルは以下のように UI/Default のシェーダを利用しています。
f:id:bluebirdofoz:20180318070535j:plain

Capasibilities の設定で"Microphone"と"Webcam"を有効にしておきます。
f:id:bluebirdofoz:20180318070543j:plain

アプリを起動します。起動直後はテクスチャは表示されていません。
f:id:bluebirdofoz:20180318070550j:plain

AirTapを行うと……。
f:id:bluebirdofoz:20180318070557j:plain
その場で撮影されたキャプチャ画像がテクスチャへ反映されました。成功です。