AR/MR,C#,Unity Unity+VuforiaでAR開発-2つの画像マーカーの距離に応じて伸び縮みするオブジェクト

Unity+VuforiaでAR開発-2つの画像マーカーの距離に応じて伸び縮みするオブジェクト

jal_ar_flexibility_topimage

UnityでAR 検証4回目

JAL都道府県シールを画像マーカーにしてUnity×vuforiaのARを検証するのも今回で4回目です。

今回の目標は
「2つの画像マーカーの間オブジェクトを表示。距離に応じてオブジェクトのスケールを変化させる」

前回まではローカル座標とワールド座標の関係を検証しましたが、単体の画像マーカーの中で完結していました。

今回は複数の画像マーカー間での座標の検証をしたいと思い目標設定しました。

それでは早速検証を始めます。

前回までの検証をまだ読んでない方は是非読んでみてください。

UnityでAR 画像マーカーで複数のオブジェクトを表示させる[Vuforia]
UnityでAR マーカーに追従しないでその場に留まるオブジェクト[vuforia]

画像マーカーが2つとも認識されたら、3個目のオブジェクトを表示する

「Osaka」 と 「Hiroshima」 の2つの画像マーカーを使います。



Hierarchyの構成は

ImageTarget_Osaka
-tutenkaku
-center_obj
– -flexibility_cube

ImageTarget_Hiroshima
-genbaku_dome

「center_obj」の名前でEnptyオブジェクトを作ってその下に表示させるオブジェクト
「flexibility_cube」を配置しました。

ImageTarget_Osakaにアタッチしたスクリプトに、

「tutenkaku」のオブジェクトと「genbaku_dome」のオブジェクトが

同時に表示されたら

「flexibility_cube」のオブジェクトを表示するコードを書きました。

public GameObject tutenkaku;
public GameObject genbaku_dome;
public GameObject flexibility_cube;

    void Update()
    {
        MeshRenderer tutenkaku_meshRenderer = tutenkaku.GetComponent<MeshRenderer>();
        MeshRenderer genbaku_dome_meshRenderer = genbaku_dome.GetComponent<MeshRenderer>();
        MeshRenderer flexibility_cube_meshRenderer = center_obj.GetComponent<MeshRenderer>();
        
        if (tutenkaku_meshRenderer.isVisible &amp;&amp; genbaku_dome_meshRenderer.isVisible)
        {
            flexibility_cube_meshRenderer.enabled = true;
        }
        else
        {
            flexibility_cube_meshRenderer.enabled = false;
        }

}

スクリプトコードの説明

if (tutenkaku_meshRenderer.isVisible && genbaku_dome_meshRenderer.isVisible)

「tutenkaku」と「genbaku_dome」のMeshRendererをチェックして両方とも Visible 見える状態になったら

flexibility_cube_meshRenderer.enabled = true;

「flexibility_cube」を表示します。

実行します。

Osakaの画像マーカーの単体の時は「tutenkaku」しか表示されませんが、「genbaku_dome」も表示されると「flexibility_cube」が現れました。

jal_ar_flexibility_anim01

3個目のオブジェクトを2つの画像マーカーの中間に表示する

無事に「flexibility_cube」を表示させることが出来ました。

出現地点は何も設定していないので「tutenkaku」と同じ位置です。
今度は、Osaka と Hiroshima の画像マーカーの中央地点に配置したいとおもいます。

ImageTarget_Hiroshima_X + ImageTarget_Osaka_X /2
ImageTarget_Hiroshima_Z + ImageTarget_Osaka_Z /2

で座標は取得できるはずなので以下のコードを書きました。
「center_obj」にアタッチしたスクリプトに

public GameObject imageTarget_Osaka;
public GameObject imageTarget_Hiroshima;

void Update()
{
    Transform iT_Osaka = imageTarget_Osaka.GetComponent<Transform>();
    Transform iT_Hiroshima = imageTarget_Hiroshima.GetComponent<Transform>();

    Vector3 iT_Osaka_pos =  iT_Osaka.transform.position;
    Vector3 iT_Hiroshima_pos = iT_Hiroshima.transform.position;

    float center_obj_pos_x = (iT_Osaka_pos.x + iT_Hiroshima_pos.x) / 2;
    float center_obj_pos_z = (iT_Osaka_pos.z + iT_Hiroshima_pos.z) / 2;
   

    Vector3 center_obj_pos = new Vector3((center_obj_pos_x - iT_Osaka_pos.x)*20, 0.0f , (center_obj_pos_z - iT_Osaka_pos.z)*20);
    this.transform.localPosition = center_obj_pos;

}

スクリプトコードの説明

    float center_obj_pos_x = (iT_Osaka_pos.x + iT_Hiroshima_pos.x) / 2;
    float center_obj_pos_z = (iT_Osaka_pos.z + iT_Hiroshima_pos.z) / 2;

ImageTarget_Osaka と ImageTarget_Hiroshima のXとYの値をそれぞれ足して2で割りました。 

Vector3 center_obj_pos = new Vector3((center_obj_pos_x - iT_Osaka_pos.x)*20, 0.0f , (center_obj_pos_z - iT_Osaka_pos.z)*20);
this.transform.localPosition = center_obj_pos;

取得した値はワールド座標ですが「center_obj」はローカル座標で配置します。中央地点の座標とImageTarget画像マーカーの座標の差を出して20(※実物の画像マーカーのサイズから)を乗算しました。

※画像マーカーのサイズについての関連記事

UnityでAR マーカーに追従しないでその場に留まるオブジェクト[vuforia]

実行します。

ブレはありますが、ほぼ中央に配置されてそうです。

jal_ar_flexibility_anim02

2つの画像マーカーの距離に応じてオブジェクトを伸び縮みさせる

2つの画像マーカーの距離を出して「flexibility_cube」のデフォルト値に乗算したらいけるのかな?

「flexibility_cube」にアタッチしたスクリプトに以下のコードを書きました。

public GameObject ImageTarget_Osaka;
public GameObject ImageTarget_Hiroshima;


void Update()
{
    Transform iT_Osaka = ImageTarget_Osaka.GetComponent<Transform>();
    Transform iT_Hiroshima = ImageTarget_Hiroshima.GetComponent<Transform>();
    Vector3 iT_Osaka_pos = iT_Osaka.transform.position;
    Vector3 iT_Hiroshima_pos = iT_Hiroshima.transform.position;

    this.transform.LookAt(iT_Hiroshima_pos);

    float distance_target = Mathf.Sqrt((iT_Hiroshima_pos.x - iT_Osaka_pos.x) * (iT_Hiroshima_pos.x - iT_Osaka_pos.x) + (iT_Hiroshima_pos.z - iT_Osaka_pos.z) * (iT_Hiroshima_pos.z - iT_Osaka_pos.z));
    float root_obj_Scale_z = System.Math.Abs(1.0f * distance_target * 20);

    Vector3 root_obj_Scale = new Vector3(0.40773f, 0.40773f, root_obj_Scale_z);
    this.transform.localScale = root_obj_Scale;



}

スクリプトコードの説明

this.transform.LookAt(iT_Hiroshima_pos);

「ImageTarget_Osaka」「ImageTarget_Hiroshima」どちらかを向く様にしました。今回はImageTarget_Hiroshimaを向くように設定しました。

    float distance_target = Mathf.Sqrt((iT_Hiroshima_pos.x - iT_Osaka_pos.x) * (iT_Hiroshima_pos.x - iT_Osaka_pos.x) + (iT_Hiroshima_pos.z - iT_Osaka_pos.z) * (iT_Hiroshima_pos.z - iT_Osaka_pos.z));
    float root_obj_Scale_z = System.Math.Abs(1.0f * distance_target * 20);

Mathf.Sqrt()を使って「ImageTarget_Osaka」と「ImageTarget_Hiroshima」の距離を取得

「flexibility_cube」のスケールのデフォルト値1.0f(と仮定して)に取得した距離の値を掛けました。
※20は実物の画像マーカーのサイズから

Vector3 root_obj_Scale = new Vector3(0.40773f, 0.40773f, root_obj_Scale_z);
this.transform.localScale = root_obj_Scale;

「flexibility_cube」のZ値のスケールを変化させます。


それでは実行してみましょう。
距離を表示するTextオブジェクトを追加しました。

それっぽくはなってるでしょうか。画像マーカーの距離に応じでスケールが変化しています。

jal_ar_flexibility_anim03



まだまだ詰めきれてないけど今回はここで終了

まとめ

それっぽい結果にはなりましたが、きちんと理解した状態ではなく課題が見えた検証でした。

ImageTargetを作ると画像のサイズに合わせてスケールが自動で設定され、
何の何処のスケール値なのか等よくわからなかったり
画像マーカーの回転に対応してなかったり。

まだまだ検証する必要がありますね。


jal_ar_pos_stay18

UnityでAR マーカーに追従しないでその場に留まるオブジェクト[vuforia]

「画像マーカーを移動しても出現位置に留まるオブジェクト」画像マーカーはワールド座標で表示されたオブジェクトはローカル座標なのでその部分の

jal_ar_rotatearound_anim

UnityでAR 画像マーカーの周りを回転するオブジェクト[vuforia]

「画像マーカーに2つのオブジェクトを出して、1つは固定もう1つは周りを回転」です。画像マーカーを認識して表示させたオブジェクトを個別にコントロールしたいという目的です。


3DCAD/3DCG/動画編集/ゲーム開発向けクリエイターPCを低下価格で購入できるFRONTIER最新GPUも格安構成も自由に選べる!パソコン買うならBTOの【FRONTIER】


Twitter Facebook Pocket LINE はてブ

おすすめの関連記事
コチラの記事も読まれています
あわせてよく読まれている記事