Vuforia Studio 3D活用備忘録：3D内のプロパティ(メタデータ)値を利用 その３

#はじめに

Vuforia Studioでは、3DCADで作成した3DをARとして表示できるが、さらに、3Dデータ内のプロパティ値（メタデータ）を扱う事ができる。プロパティ値を利用する例を備忘録としておく。

#前提

Vuforia Studio バージョン 8.5.13 以降。
この備忘録は、Vuforia Studioで、3DデータをAR表示させ、同時に2D画面上に2Dウィジェットを表示させ、さらにホームJSにJavaScriptコードを追加するARの作成経験がある人が対象。
また、以下の備忘録**その１**を試し済みの人が対象。
・[Vuforia Studio 3D活用備忘録：3D内のプロパティ(メタデータ)値を利用 その１](
https://qiita.com/tm181001/items/a70b1ec243d1ab559a5c)

#3Dデータについて

本備忘録では、3DCADのSolidWorxsの3Dデータを使った。Vuforia Studioは様々な3DCADデータに対応しているので、他の3DCADデータでも本例と同様の事が出来る。

#3D内のプロパティ(メタデータ)値を表示し、選択すると該当パーツの色を変更する例

**その１**では、下図のようにパーツとアセンブリのデータを取得して、一覧表示を試した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297270/c827b84a-bad9-e99f-c534-b4cf8c090e4f.png)
今回は、**その１**に対して、一覧表示でパーツを選択したら、ARの3Dの該当箇所の色を変更してみる。

###一覧表示で選択したパーツのIDパスを取り出す準備

Vuforia Studioで扱う3Dデータにおいて個々のパーツを識別するには、IDパスを使う。「Part ID Path」の値がIDパスなのだが、一覧表示させている選択ウィジェットの表示フィールドや値フィールドの指定に半角スペースがあると、うまく動いてくれない模様。そこで、プロパティに半角スペースの無い「PartIDPath」キーを追加して「Part ID Path」の値をコピーして使ってみる。

```javaScript:
    // 作成した表示名を、「IndentName」の値として追加する
    partsysprop['IndentName'] = partdepth + indent + partname;
    // IDパスを、「PartIDPath」の値として追加する
    partsysprop['PartIDPath'] = idpath;
    parts.push(partsysprop);
```
コードに、partsysprop['PartIDPath'] = idpath;　を追加して値をコピーする。

それから、3Dのパーツとアセンブリのデータを一覧表示している選択ウィジェットの値フィールドに、「PartIDPath」を入力する。これで、一覧からパーツを選択したら、そのIDパスをdataとして取り出せる。そのdataを使う処理として、イベントの値変更のJS欄に、selectPart(data); を入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297270/b343315c-f57f-12d0-591e-68fe1c8f28e3.png)

###一覧表示で選択したパーツのIDパスを確認する

ARの3Dのパーツの色を変更させていく前に、選択したパーツのIDパスを取り出せているかを簡易確認してみる。選択ウィジェットの値変更のJS欄入力した selectPart(data); により実行されるファンクションを以下のようにホームJSに追加する。

```javaScript:
$scope.selectPart = function(data){
  alert(data);
}
```
プロジェクトを保存して、プレビューしてみる。どうやらIDパスを取り出せているようだ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297270/e81e46b5-05ff-f5d3-d122-1d575d25e02e.png)

###選択したIDパスに対するARの3Dのパーツの色を変更する

モデルウィジェットのIDと、IDパスとをハイフン「-」で連結して3Dのパーツを特定して、setColor() でそのパーツの色を変更できる。上記の $scope.selectPart の箇所を、以下のコードに変更する。

```javaScript:
var PICK_COLOR  = "rgba(255,255,0,1)"; // 黄色
var lastSelection = '';

$scope.selectPart = function(data){
  //alert(data);
  // 前の選択のパーツの設定を変更する
  try{
    // 色の変更を解除する
    tml3dRenderer.setColor(lastSelection, undefined);
  }
  catch (ex) {
    alert(ex);
  }
  // 今回の選択のパーツの設定を変更する
  lastSelection = modelName + "-" + data;
  try{
    // 色を変更する
    tml3dRenderer.setColor(lastSelection, PICK_COLOR);
  }
  catch (ex) {
    alert(ex);
  }
}
```
プロジェクトを保存し、プレビューにてパーツを選択してみる。おぉ、色が変わった。出来た！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297270/4bab8034-9bf0-ddd3-3e5f-cd31d7205cad.png)

###選択したパーツが内部にあっても見えるようにする（常に手前に表示する）

以下のコードのように、setProperties(lastSelection, {decal: true})　を追加することで、選択したパーツが内部にあっても、常に手前に表示する設定となり、見えるようになる。選択解除時には、false にしてその設定を解除しておく。

```javaScript:
  // 前の選択のパーツの設定を変更する
  try{
    // 色の変更を解除する
    tml3dRenderer.setColor(lastSelection, undefined);
    // 常に前に表示を解除する
    tml3dRenderer.setProperties(lastSelection, {decal: false});
  }
  catch (ex) {
    alert(ex);
  }
  // 今回の選択のパーツの設定を変更する
  lastSelection = modelName + "-" + data;
  try{
    // 色を変更する
    tml3dRenderer.setColor(lastSelection, PICK_COLOR);
    // 常に前に表示を設定する
    tml3dRenderer.setProperties(lastSelection, {decal: true});
  }
  catch (ex) {
    alert(ex);
  }
}
```
プレビューにて内部にあるパーツを選択してみたら、見えるようになった！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297270/e541f275-c4dc-53a0-0fdf-7e0d0109a87f.png)


###選択したパーツのみを表示する

ARの3Dを実物に重ね合せ表示する場合には、3Dアセンブリ全体は非表示にして、ハイライトしたいパーツのみを表示させたいことがある。それを試してみる。モデルウイジェットの表示プロパティのチェックを解除して、デフォルトで3Dを非表示にしておく。以下のコードのように、setProperties(lastSelection, {hidden: false})　を追加することで、選択したパーツを表示する。選択解除時には、true にして非表示にする。

```javaScript:
  // 前の選択のパーツの設定を変更する
  try{
    // 色の変更を解除する
    tml3dRenderer.setColor(lastSelection, undefined);
    // 常に前に表示を解除する
    //tml3dRenderer.setProperties(lastSelection, {decal: false});
    // 非表示にする
    tml3dRenderer.setProperties(lastSelection, {hidden: true});
  }
  catch (ex) {
    alert(ex);
  }
  // 今回の選択のパーツの設定を変更する
  lastSelection = modelName + "-" + data;
  try{
    // 色を変更する
    tml3dRenderer.setColor(lastSelection, PICK_COLOR);
    // 常に前に表示を設定する
    //tml3dRenderer.setProperties(lastSelection, {decal: true});
    // 表示にする
    tml3dRenderer.setProperties(lastSelection, {hidden: false});
  }
  catch (ex) {
    alert(ex);
  }
```
すると、選択したパーツのみが表示されるようになる。出来た！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297270/47fbb829-6ee8-3bc2-8583-ea1a3b179625.png)

###選択したパーツを点滅する（不透明度を変更する）

以下のコードのように、不透明度(opacity)の値を1.0 にして元に戻す処理 setProperties(lastSelection, {opacity: 1.0}); を追加する。

```javaScript:
  // 前の選択のパーツの設定を変更する
  try{
    // 色の変更を解除する
    tml3dRenderer.setColor(lastSelection, undefined);
    // 常に前に表示を解除する
    //tml3dRenderer.setProperties(lastSelection, {decal: false});
    // 非表示にする
    tml3dRenderer.setProperties(lastSelection, {hidden: true});
    // 不透明にする
    tml3dRenderer.setProperties(lastSelection, {opacity: 1.0});
  }
  catch (ex) {
    alert(ex);
  }
  // 今回の選択のパーツの設定を変更する
  lastSelection = modelName + "-" + data;
  try{
    // 色を変更する
    tml3dRenderer.setColor(lastSelection, PICK_COLOR);
    // 常に前に表示を設定する
    //tml3dRenderer.setProperties(lastSelection, {decal: true});
    // 表示にする
    tml3dRenderer.setProperties(lastSelection, {hidden: false});
  }
  catch (ex) {
    alert(ex);
  }
```
そして、選択したパーツを、不透明度の変更で 1秒(1000ミリ秒)ごとに点滅する、以下のコードを追加する。

```javaScript:
// 点滅
var blink = true;
var opacityV = 0.9;
var opacityL = 0.4;
var opacityH = 0.9;
$scope.startAnimation = function(){
  var timerId = setInterval(function() {
    $scope.$apply(function(){
      if(blink){
        if(opacityV>0.5){
          opacityV = opacityL;
        }
        else{
          opacityV = opacityH;
        }
        if(lastSelection && lastSelection.length>0){
          tml3dRenderer.setProperties(lastSelection, {opacity: opacityV});
        }
      }
    })
  }, 1000 );
}
```
プレビューで確認したら、点滅出来た！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297270/0b0fea14-82b7-b5a3-9eb3-d7c019e5648e.png)

#おわりに

3DCADデータには、製造に必要なデータ、保守に必要なデータなどを、プロパティ値（メタデータ）として含める事も多い。そのデータをARでも利用すれば、製造、保守に簡単に活用できる。積極利用すべきだと思う。
本備忘録では、**その３**として、パーツとアセンブリのデータの一覧表示で選択したパーツの色変更などを試した。モデルアイテムウィジェットによるパーツ指定を逐一しなくても、多くのパーツを対象にして色変更、手前表示、表示/非表示、不透明度変更が可能なのは使い勝手が良い。

#注意

3DCADデータのアセンブリやパーツ名（構造名）に日本語を使っている場合、jsonファイルでは日本語部分が文字化けするようなので注意。

#参考

・[Vuforia Studio 3D活用備忘録：3D内のプロパティ(メタデータ)値を利用 その１](
https://qiita.com/tm181001/items/a70b1ec243d1ab559a5c)

・[Vuforia Studio 3D活用備忘録：3D内のプロパティ(メタデータ)値を利用 その４　カスタムプロパティ一覧を表示する](https://qiita.com/tm181001/items/8a4d760148e26e1a3b84)

・[エクスペリエンスへの CAD メタデータの組み込み @ Vuforia Studioヘルプ](
http://support.ptc.com/help/vuforia/studio/ja/#page/Studio_Help_Center%2Fcad_metadata_api.html)

・[Incorporate CAD Metadata Into an Experience ( version 8.5.13 and later) @ ptc community](https://community.ptc.com/t5/Vuforia-Studio-and-Chalk-Tech/Incorporate-CAD-Metadata-Into-an-Experience-version-8-5-13-and/ta-p/693341)

・[Vuforia Studio - introduction to MetaData Video @ ptc community](https://community.ptc.com/t5/Vuforia-Studio/Vuforia-Studio-introduction-to-MetaData-Video/td-p/695630?posno=6&q=Metadata%20Vuforia&source=search)