2017年7月11日 更新

VR解剖アプリを作る その2 ~Unity上でCTデータを扱う~

3DデータをUnityに取り込んで、カメラで観察するアプリを作ります。 非VRとVRを実装します。

6,220 view お気に入り 1

基準点に必要な挙動は回転とズームでした。

今回つけた機能は以下の通りです。

  • スワイプでθ、φ変位(それぞれスワイプの縦成分、横成分が対応)
  • キー操作でr変位(Wで拡大、Qで縮小)
  • キーボードEで視点リセット
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PolarCoordinates : MonoBehaviour {
    public GameObject origin; // 原点
    public Camera camera; // 使用するカメラ
    public float swipeMoveSpeedX = 0.01f; // スワイプで移動するスピード
    public float swipeMoveSpeedY = 0.01f; // スワイプで移動するスピード

        public float theta = 90 * Mathf.Deg2Rad; // 極座標角度パラメータθ
        public float phai = 0 * Mathf.Deg2Rad; // 極座標角度パラメータφ
        public float r = 5; // 極座標距離r(ReferencePointの座標から算出)
        public float diffR = 1; // ズーム単位

    private Vector3 baseMousePos; // 基準となるタップの座標
    private Vector3 baseCameraPos; // 基準となるカメラの座標
    private bool isMouseDown = false; // マウスが押されているかのフラグ

        public void UpdatePosition() {
                // θ,φの変位を直交座標の変位に変換する
                float newX = r * Mathf.Sin(theta) * Mathf.Cos(phai);
                float newY = r * Mathf.Cos(theta);
                float newZ = r * Mathf.Sin(theta) * Mathf.Sin(phai);

                if (theta > 0 && theta < 180 * Mathf.Deg2Rad) {
                        this.transform.position = new Vector3 (newX, newY, newZ);
                }

                // 原点にむけてRotationを修正
                transform.LookAt(new Vector3 (0, 0, 0));
        }

        public void ResetPosition() {
                // ハードコーディング。イケてない
                theta = 90 * Mathf.Deg2Rad;
                phai = 0 * Mathf.Deg2Rad;
                r = 5;
                UpdatePosition();
        }

        // Use this for initialization
        void Start () {
        }
        
        // Update is called once per frame
        void Update () {

                // スワイプの判定
                if ((isMouseDown)|| Input.GetMouseButtonDown(0)) {
                        baseMousePos = Input.mousePosition;
                        isMouseDown = true;
            isAutoRotate = false;
                } 

        // 指離した時の処理
                if (Input.GetMouseButtonUp(0)) {
                        isMouseDown = false;
                        basePinchZoomDistanceX = 0;
                        basePinchZoomDistanceY = 0;
                }
                
                // 回転
                if (isMouseDown) {
                        // マウスグリグリ動かすことでここが変化する
                        Vector3 mousePos = Input.mousePosition;
            Vector3 distanceMousePos = (mousePos - baseMousePos);

                        // スワイプの距離が極座標のθ,φに相当する
                        float swipeX = distanceMousePos.x * swipeMoveSpeedX;
                        float swipeY = distanceMousePos.y * swipeMoveSpeedY;
                        theta += swipeY;
                        phai += swipeX;

                        UpdatePosition();
                        baseMousePos = mousePos;
                }

                // ズーム
                if (Input.GetKeyDown(KeyCode.Q)) {
                    r += diffR;
                        UpdatePosition();
                } else if (Input.GetKeyDown(KeyCode.W)) {
                    r -= diffR;
                        UpdatePosition();
                }

                // リセット
                if (Input.GetKeyDown(KeyCode.E)) {
                        ResetPosition();
                } 

                if (Input.GetKeyDown(KeyCode.JoystickButton0)) {
                        ResetPosition();
                } 
        }
}
PolarCoordinates.cs


カメラに必要な挙動は基準点からの移動です。

今回つけた機能は以下の通りです。

  • キーボードの方向キーでxy変位
  • キーボードEで位置リセット
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraMove : MonoBehaviour {
        public float diffPosition = 0.05f; // 移動単位

        public void ResetPosition() {
                this.transform.localPosition = new Vector3 (0, 0, 0);
        }

        // Use this for initialization
        void Start () {
                
        }
        
        // Update is called once per frame
        void Update () {
                
                // 移動
                if (Input.GetKey(KeyCode.UpArrow)) {
                    this.transform.localPosition += new Vector3 (0, diffPosition, 0);
                } else if (Input.GetKey(KeyCode.DownArrow)) {
                    this.transform.localPosition -= new Vector3 (0, diffPosition, 0);
                } else if (Input.GetKey(KeyCode.LeftArrow)) {
                    this.transform.localPosition -= new Vector3 (diffPosition, 0, 0);
                } else if (Input.GetKey(KeyCode.RightArrow)) {
                    this.transform.localPosition += new Vector3 (diffPosition, 0, 0);
                }

                // リセット
                if (Input.GetKeyDown(KeyCode.E)) {
                        ResetPosition();
                } 
        }
}
CameraMove.cs


VR解剖図 HoloLensアプリ

実装した結果このような挙動を実現できます。
回転、移動、ズームを組み合わせることで任意の点を観察することができるようになりました。


VRアプリ: ジャイロ機能

VRアプリでは画面操作はできません。

コントローラを用意しない場合は、主に首振りや視線で操作することになります。

今回は複雑なものは実装せず、3Dモデルを首振りで観察することを目指します。

スマホのジャイロ機能を使用します。



加えてVRアプリ化を施す必要があります。

現在、UnityでVRアプリを作ろうと思ったら例として以下の2つの選択肢が取れます。

  • Google VR SDK for Unityを使う
  • UnityのVR support機能を使う

UnityのVR機能はまだ新しいものですが、今後この組み込み機能を使うのがスタンダードとなるでしょう。

外部ライブラリに依存させたくないので今回はこちらを選択します。



ちなみに今回はAndroid向けに作っていきます。



VR設定

 (4110)

「File-> Build Settings-> Player Settings」でInspectorウィンドウが表示されます。
ドロイド君のマークが選択されていることを確認します。
 (4111)

「Inspector-> Other Settings-> Virtual Reality Supported」にチェックします。
Virtual Reality SDKは何かしらを選択しなくてはいけないのでCardboardを選択しておきます。
多分Noneでもいけると思います。

Minimum API Levelを要求通りに上げ、Bundle Identifierを適当に設定します。



対応オブジェクトを作る

49 件

関連する記事 こんな記事も人気です♪

VR解剖アプリを作る その1 ~CTスキャンの結果から3Dデータを得る~

VR解剖アプリを作る その1 ~CTスキャンの結果から3Dデータを得る~

VR解剖アプリを作る連載物です。今回はOsiriXというソフトを使ってCTのデータから3Dデータを作成しました。
山田涼太 | 9,364 view
CTの原理①~ラドン変換~

CTの原理①~ラドン変換~

CTの原理に関して詳しく説明します. 今回はRadon変換についてです.
医療×人工知能の最前線を追え‼ 「人工知能エンジニアMeetUp!#4〜AI医療画像診断支援 & RSNA報告会〜 」のまとめ。Part 2

医療×人工知能の最前線を追え‼ 「人工知能エンジニアMeetUp!#4〜AI医療画像診断支援 & RSNA報告会〜 」のまとめ。Part 2

今回の記事は、前回投稿したLPixel主催MeetUp記事のPart2です!医師である龍さんと講演後の懇親会の様子を振り返ってみようと思います。 この記事はLpixelインターンの北村が担当しています。
北村 旭 | 4,268 view
About IMACEL Academy

About IMACEL Academy

人工知能・画像解析スキルが身につく専門サイト-IMACEL Academy-についてです

この記事のキーワード

この記事のキュレーター

山田涼太 山田涼太