Rust製pastelコマンドにimas色機能を追加する

はじめに

Rust製pastelコマンドとは以下のやつです。

github.com

(gifはリポジトリから拝借)

pastel is a command-line tool to generate, analyze, convert and manipulate colors. It supports many different color formats and color spaces like RGB (sRGB), HSL, CIELAB, CIELCh as well as ANSI 8-bit and 24-bit representations.

つまり、CLI上で色に関することをいろいろできるということですね。
その"いろいろ"を実現するために、様々なサブコマンドがあります。
そこにimasを追加して、アイドルやユニットのイメージカラーを取得できるようにしてみました。

pastel 0.8.1
A command-line tool to generate, analyze, convert and manipulate colors

USAGE:
    pastel [OPTIONS] <SUBCOMMAND>

OPTIONS:
    -m, --color-mode <mode>              Specify the terminal color mode: 24bit, 8bit, off, *auto*
    -f, --force-color                    Alias for --mode=24bit
        --color-picker <color-picker>
            Use a specific tool to pick the colors [possible values: gpick, xcolor,
            grabc, colorpicker, chameleon, kcolorchooser]
    -h, --help                           Prints help information
    -V, --version                        Prints version information

SUBCOMMANDS:
    color         Display information about the given color
    list          Show a list of available color names
    random        Generate a list of random colors
    distinct      Generate a set of visually distinct colors
    sort-by       Sort colors by the given property
    pick          Interactively pick a color from the screen (pipette)
    format        Convert a color to the given format
    paint         Print colored text using ANSI escape sequences
    gradient      Generate an interpolating sequence of colors
    mix           Mix two colors in the given colorspace
    colorblind    Simulate a color under a certain colorblindness profile
    set           Set a color property to a specific value
    saturate      Increase color saturation by a specified amount
    desaturate    Decrease color saturation by a specified amount
    lighten       Lighten color by a specified amount
    darken        Darken color by a specified amount
    rotate        Rotate the hue channel by the specified angle
    complement    Get the complementary color (hue rotated by 180°)
    gray          Create a gray tone from a given lightness
    to-gray       Completely desaturate a color (preserving luminance)
    textcolor     Get a readable text color for the given background color
    imas          Get a Im@s idol's image color from im@sparql.      <---  こんな感じ!!!
    help          Prints this message or the help of the given subcommand(s)

↑ サブコマンドに追加

そして、出来上がったものがこちら

github.com

f:id:crssnky:20210801232936p:plain

こんな感じになります。
それでは解説していきます。

Rustからim@sparqlを叩く

im@sparqlへのクエリは以下になります。

REFIX imas: <https://sparql.crssnky.xyz/imasrdf/URIs/imas-schema.ttl#>
PREFIX imasrdf: <https://sparql.crssnky.xyz/imasrdf/RDFs/detail/>

SELECT distinct ?c 
WHERE {
  imasrdf:{} imas:Color ?c
}

今回は軽めの実装にするため、im@sparql内のリソース名を入力してもらうようにします。ですのでimasrdf:{}{}には、アイドルやユニットのリソース名(Kisaragi_Chihayaやnoctchillなど)が入ります。

シリアライズの詳しい内容は過去の記事へ。だいたい一緒です。

crssnky.hatenablog.jp

imas.rsファイルをcommandsフォルダに作成して処理を作ります(コード)。
HTTP GETするURLは以下のように作ります。form_urlencodedを利用すれば、クエリストリングを良い感じにしてエンコードまでしてくれます。
また、ureq::get().call()であれば同期処理でコールします。今回のようなものは、コールバック書かなくて良いのでラクですね。

    let encoded_query = form_urlencoded::Serializer::new(String::new())
      .append_pair("output", "json")
      .append_pair("force-accept", "text/plain")
      .append_pair("query", &query)
      .finish();
    let sparql_url = format!(
      "https://sparql.crssnky.xyz/spql/imas/query?{}",
      encoded_query
    );

    let res = ureq::get(&sparql_url).call();
    if res.ok() {
・・・
    }

im@sparqlのレスポンスを解釈する

受け取ったJSONを構造体に変換し、カラーコードを抜き出してColor構造体に変えているだけです。u8::from_str_radixを使えば、Hex文字列から数値に変換してくれます。

      let json_str = res.into_string().unwrap();
      let res_json: Response = serde_json::from_str(&json_str).unwrap();
      let json = res_json.results.bindings;
      if json.len() > 0 {
        for data in json {
          let color_string = &*(data.c.value);
          if color_string.len() >= 6 {
            let red: u8 = u8::from_str_radix(&color_string[0..2], 16).unwrap();
            let green: u8 = u8::from_str_radix(&color_string[2..4], 16).unwrap();
            let blue: u8 = u8::from_str_radix(&color_string[4..6], 16).unwrap();
            let color = Color::from_rgb(red, green, blue);
            out.show_color(&config, &color)?;
          }
        }
      }

imasコマンドを追加する

まずは、mod.rsファイルです(コード)。
上部のmod郡にimasを追加します。また、imas:ImasCommandを使うよう指定します。

mod imas;
use imas::ImasCommand;

あとは、imasというサブコマンドを実行したときに、imas:ImasCommandが使われるようimpl Commandpub fn from_string()に指定します。

      "colorcheck" => Command::Generic(Box::new(ColorCheckCommand)),
      "imas" => Command::Generic(Box::new(ImasCommand)),   // これ
      _ => unreachable!("Unknown subcommand"),

次にcli.rsファイルです(コード
サブコマンドがたくさん並んでいますので、そこにimasコマンドの引数やヘルプを書いておきます。

.subcommand(
    SubCommand::with_name("imas")
        .about("Get a Im@s idol's image color from im@sparql.")
        .long_about("Get a Im@s idol's image color from im@sparql.\n\n\
        Example:\n  \
          pastel imas Kisaragi_Chihaya")
        .arg(color_arg.clone()),
)

おわりに

以上が解説です。これを応用すれば、色に関する様々なアプリケーションを作成できると思います。
特に元から実装されている可視化部分がよく出来ています。imasコマンドも色を取ってきて、Color構造体に入れるだけで良い感じに可視化されるため、色を取得する部分だけでもカスタムすると面白いと思います。

HoloLens2で北朝鮮のミサイル実験を可視化 with UE4

デモ

発表資料

(16:9のスライドは埋め込みだと崩れちゃうか~) speakerdeck.com

はじめに

Tokyo HoloLens ミートアップ vol.26ではありがとうございました。
発表ではめちゃくちゃ駆け足になってしまったため、詳細に解説していきます。
内容としては、UE4を利用してHoloLens2で北朝鮮のミサイル実験を可視化した話です。
記事がめちゃ長くなりそうだったので、各要素ごとで記事にしています。
(弾道ミサイルのことはよく分からなくても記事が読めるように...)

HoloLens2とは

www.microsoft.com

みなさんご存知のMicrosoftが提供するMixedRealityデバイスです。
ゴーグル型のこのデバイスを着けることで、複合現実を利用することができます。
PC等に接続せずスタンドアロンで動作し、デバイスに外向きに取り付けられたカメラで周囲の形状や装着者の手の動きを認識します。
それこそが"複合現実"です。

データ

crssnky.hatenablog.jp

地球儀

crssnky.hatenablog.jp

UEGeoCoordinates Plugin

crssnky.hatenablog.jp

MRTK For Unreal UX Tools

crssnky.hatenablog.jp

まとめ

HoloLens2、UnityもいいけどUE4もよろしくね!

UE4向けMRTK UX ToolsとUMGでらくらくUI作り

はじめに

https://crssnky.hatenablog.jp/entry/2021/BMD

↑の子記事となっています。記事の背景を知る場合はこちらから参照ください。

MRTK UX Toolsとは

github.com

Mixed Reality Tool Kitはみなさんご存知かと思いますが、それのUE4版の主なツールキットです。
UE4ではUX Toolsの他に、Graphics ToolsというMR向けマテリアルキットがあります。

UMGとは

docs.unrealengine.com

誤解を恐れずに言えば、GUIとBlueprintで記述可能なUIシステムです。
ゲーム内はもちろん、UE4 Editorの拡張機能を作る場合にも使えます。

デモ

f:id:crssnky:20210711165616p:plain

こういうハンドメニューだったり、

f:id:crssnky:20210711165943p:plain

UMGのListViewだって置けちゃいます。
今回は、この2つのUIを例に解説します。

ハンドメニュー

https://github.com/microsoft/MixedReality-UXTools-Unreal/blob/public/0.12.x/Docs/HandMenu.md

公式ドキュメントとやっていることは変わらない。

f:id:crssnky:20210711171047p:plain

見た目とコンポーネントはこのようになっています。
SceneComponentはRootをUxtUIElementにします。
ここに、UIの部品を入れていくわけですが、単純なSceneComponentによるPivotを一個挟むことを個人的にはオススメします。
というのも、位置を調整できるようにしないと、デフォの位置では下記画像のように手に埋まってしまう可能性があります。

f:id:crssnky:20210711172447p:plain

X軸方向にズラしましょう。僕は8くらい移動させています。


UxtBackPlateはUIの背景用のコンポーネントです。ただのStaticMeshComponentではなく、UX Toolsのカスタム?品です。
下記画像を見てください。有る無しでは、UIのまとまり感がぜんぜん違うと思います。

f:id:crssnky:20210711173031p:plain


各種ボタンについては、ChildActorComponentで他のBlueprintファイルを埋め込む形を取っています。
それらの解説は次の章へ

各種ボタン

https://github.com/microsoft/MixedReality-UXTools-Unreal/blob/public/0.12.x/Docs/PressableButton.md

ボタンに関しても、公式ドキュメントと変わらない。

f:id:crssnky:20210711174707p:plain

UxtPressableButtonを継承したBlueprintで作ります。
そうすれば、各種プロパティをいじるだけで良い感じのボタンになるでしょう。
いじるのは以下のプロパティです。BlueprintのDetailsにあります。

f:id:crssnky:20210711175413p:plain

ボタンのサイズやアイコン、ラベルを好きに変えていきましょう。

f:id:crssnky:20210711180106p:plain

ボタンにはたくさんのイベントが用意されています。困りませんね。

ListView

https://github.com/microsoft/MixedReality-UXTools-Unreal/blob/public/0.12.x/Docs/WidgetComponent.md

UMGであるListView(Widget)を入れる方法の公式ドキュメントはこちら↑

え?BlueprintだけでListViewを作る方法がわからないって?だったら下記のForumを参考にすると良いですよ。僕はこれに何度も救われています(いつまで経っても覚えていない)

forums.unrealengine.com

ListViewのUMGファイルを作ったあとということで進めていきます。

f:id:crssnky:20210711180956p:plain

見た目とコンポーネントはこのようになっています。
UxtFollowは、HoloLens2の向きにUIを追従させるためのActorComponentであり、SceneComponentではないのですが、なぜかSceneComponentの場所に入っています。なんでやねん。

f:id:crssnky:20210711182624p:plain

ちゃんと、Non-scene componentって書いてある↑


UxtWidgetは、UMGに触れられるように、手の当たり判定とUMGをつなぐためのコンポーネントです。
これと、Widgetコンポーネントを配置することで、触れられるUMGを表示して操作することができます。WidgetコンポーネントはちゃんとScreenSpaceではなく、WorldSpaceに配置するように設定してくださいね。
ちなみに、ListViewのスクロールは右のスクロールバーで行います。スマフォでよくあるListView全体をぐいーってスライドしてもスクロールしませんからね!(僕はその罠に嵌りました)


UxtBackPlateは前述の通り背景用です。これが無ければ本当に背景がありません。


CloseButonは、このBlueprintを閉じるためのボタンです。UMG側に用意するとWidgetだけ閉じられてしまうので、Blueprint自体をDestroyできるようにBlueprint側で用意します。
(今思えば、Widget側でイベント発行してBlueprintで受信すれば良かったか?)

f:id:crssnky:20210711182843p:plain

おわりに

以上、簡単なボタンを持つUIやUMGを埋め込んだUIを作る方法でした。正直、UMGが使えてしまうのであればなんでもできちゃうので、HoloLens2のUIに関してはできないことが無いと思います。
とはいえ、UX Toolsの標準的な見た目のみを使っているため、見た目に凝ったUIに関しては制約があるかもです....

UE4のUEGeoCoordinates PluginでGeocentricしてみる

はじめに

https://crssnky.hatenablog.jp/entry/2021/BMD

↑の子記事となっています。記事の背景を知る場合はこちらから参照ください。

UEGeoCoordinates Pluginとは

github.com

EpicGamesが作っているUE4の公式プラグインです。
最初に言うと、このプラグインUE4.26向けにプレビュー版として公開されており、次期バージョンのUE4.27では"GeoReference Plugin"として標準搭載されています。
もちろん、今回お話する内容はUE4.26向けのプレビュー版です。4.27ではたぶん違います。ソース見たら違ったし...

UEGeoCoordinates Pluginは、おそらく"Project Anywhere"のために作られたと予想します。現実の座標(緯度経度など)を表すためのクラスや倍精度浮動小数点を使った座標クラスなど、シミュレーション用途で必要そうなものが揃っているので。
このプラグインの使い方や現実での座標の考え方は、プラグインリポジトリにPDFがあるのでそれを見ると分かります。座標の考え方や座標参照系など、馴染みが薄いものが分かりやすい英語と図で解説されているのでここで書く必要は無いでしょう。

Geocentricしてみる①

Geocentric coordinate systemとは、いわゆる地心座標系です。
地球の中心を(0,0,0)とし、北極点をZ軸方向、本初子午線をX軸方向、東経90度方向をY軸方向とする座標系です。単位はmで、3D界隈の人にはとっつきやすいものかと思います。
(Y軸が上方向でしょ。など、軸に関しては言いたいこともあるかもですが...)

これをね、そのままUE4に適用しちゃえば良いって話ですよ。
BP関数はこちら↓
f:id:crssnky:20210711011839p:plain

Geographical coordinate systemは、いわゆる地理座標系です。ですので、この関数の入力は緯度, 経度, 高度(Lat, Lon, Alt)です。

プラグインのSubsystemからGeographic to Geocentric関数を呼び出すだけで変換できます。ただ、出力は倍精度浮動小数点を使った座標クラスであり、単精度浮動小数点数を使うVector3では使えません。自作の関数で、泣く泣く精度を下げています。

Geocentricしてみる②

Blueprint内で緯度経度からXYZに変換する方法は分かりました。しかし、Level内に原点を設定する必要があります。
f:id:crssnky:20210711012603p:plain

GeoreferecingActorをLevelに置きましょう。これ自体の座標は関係ありませんが、Origin Projected Coordinatesや各種CRS(座標参照系)を指定してあげる必要があります。
f:id:crssnky:20210711012839p:plain

Origin Projected Coordinatesは原点にしたいLevel内の座標を指定します。何も考えず、(0,0,0)でも問題ないです。
CRS(座標参照系)は、プラグインのPDFの通り、https://epsg.io/ で探しましょう。"CRS Tokyo"などでGoogleで調べても良いかもしれません。
入れたい緯度経度が日本周辺だったため、上記画像の値は東京となっています。

GeoreferencingSubsystemはこのActorの設定値を読み取り、適切な変換を行います。

おわりに

変換すれば、以下のように良い感じで緯度経度をUE4のワールド座標に変換することができます。
(これは発射点と着地点の間に最高点を入れて補間してるけどね)

UE4でHoloLens2でも使える、昼夜を表す地球儀を作ろう

はじめに

https://crssnky.hatenablog.jp/entry/2021/BMD

↑の子記事となっています。記事の背景を知る場合はこちらから参照ください。

また、昼夜を表せられる地球儀をサクッと作りたい方向けです。
そんなに精密なものではありません。

デモ

このような感じで、昼夜のテクスチャを向きで切り替える地球儀です。

テクスチャ

地球の画像と言えば、やはりNASAのBlueMarbleでしょう。

NASA Visible Earth - Home

この中から、昼の地球と夜の地球を選びます。
夜の地球は一枚しかない(Earth’s City Lights)ので良いのですが、昼の地球(Blue Marble Next Generation)はいろいろな季節のものがあります。お好きなものを選びましょう。

モデル

球体であればなんでもいいです。
僕はBlenderで65280頂点の球体を作りました。それくらいでもHoloLens2は余裕みたいです。

マテリアル

UE4のお時間です。全容はこちら↓
f:id:crssnky:20210710230552p:plain

おそらくこれはBestWayじゃないだろうけども、許してね。

まず下段ここ
f:id:crssnky:20210710231538p:plain ここですが、ラフネスを求めています。
海の部分だけ強く反射してほしい気分だったので、なんか良い感じに求めています。
(理論は無く、本当に"良い感じで"求めました)
そうすると、以下のような感じになります。
f:id:crssnky:20210710231249p:plainf:id:crssnky:20210710231330p:plain

次は上段ここ f:id:crssnky:20210710232749p:plain ここは、外から入力された光の向き(Vec4)と、ローカル座標の内積を取得しています。
マテリアルに当たる光をDirectionalLightにすることで、昼夜の判定を模擬します。
光と内積については、以下ブログの"セルシェーダーと内積"の章を見ると分かりやすいです。

UE4 誰でもわかるセルシェーダー入門 - Let's Enjoy Unreal Engine

最後はここ f:id:crssnky:20210710233912p:plain 内積による昼夜の判定から、ifノードで表示するテクスチャを選択しています。
Emissiveにも入れることでDirectionalLightしか無い宇宙空間でも、光の当たらない方を見せることができます。

Blueprint

コンポーネントはこんな感じです↓
f:id:crssnky:20210710235148p:plain

SceneComponent系は、StaticMeshComponentだけです。作った球体メッシュに作ったマテリアルを貼ってあげましょう。

ActorComponent系は、HoloLens2による入力を受けるためのコンポーネントです。主にTransformを変えるためのものです。説明は割愛。

マテリアルで取得するための光の向きはBlueprintで入れます。
f:id:crssnky:20210711000616p:plain このようなBP関数を作り、ConstructionScriptはもちろん、Tickなどで定期更新してあげましょう。常にTickを呼ぶのはアレなので、僕はHoloLens2がGrabしているだけTickするようにしています。

おわりに

以上です。簡単!環境によっては、画像をDLする時間やマテリアルをビルドする時間の方が手を動かす時間より長いかもしれませんね。
説明は割愛しましたが、HoloLens2のMRTKのコンポーネントを入れることで、自分の手で動かしたり回したりできます。まさに地球儀です。
ここになにか情報を重畳してあげることで、MRでリッチな自分だけの地球儀を作れるようになると思います。

cereal-UE4でJSONデータを読み込む

はじめに

https://crssnky.hatenablog.jp/entry/2021/BMD

↑の子記事となっています。記事の背景を知る場合はこちらから参照ください。

データ

github.com

実は、北朝鮮のミサイル実験のJSONデータはこのリポジトリにまとまっています。
このリポジトリは、元々Webアプリケーションとしてミサイル実験の可視化を行うプロダクト(ReadMe参照)のものですが、そこに使われているものがよくまとまっており、定期的に更新もされているため非常に使いやすいです。
本プロジェクトでは、

  • test.ja.json(各実験概要)
  • missile.ja.json(ミサイルリスト)
  • facility.ja.json(施設...ですが、分かりやすく言えば発射地点リスト)

を読み取ります。

ライブラリ

読み取りに使うのは、cerealというC++JSONライブラリです。UE4で扱うため、cereal-UE4も追加で入れます。
使い方は、伊藤兎さんのcereal-UE4に関する記事を読むと分かりやすいです。

GitHub - USCiLab/cereal: A C++11 library for serialization

GitHub - usagi/cereal-UE4: cereal ( C++ serialization library ) adapter for UE4 ( Unreal Engine ) types

usagi.hatenablog.jp

元データは以下のような形のため、C++で非常に解釈しづらいです。

{
    "er-scud": {"name": "スカッドER", "type": "MRBM"},   // keyに名前が入っている
    "hwasong-12": {"name": "火星12号", "type": "IRBM"}, 
    ....
}

ですので、自前で良い感じに整形してから(前処理として)、C++で読み込んでいます。

{
  "root": {
    "missiles": [
      {
        "key": "er-scud",   // 名前をvalue側に移した
        "name": "スカッドER",
        "type": "MRBM"
      },
      {
        "key": "hwasong-12",
        "name": "火星12号",
        "type": "IRBM"
      },
      ....
}

これならば、以下のC++で読めますね。

USTRUCT(BlueprintType)
struct FMissile {
    GENERATED_BODY()
        UPROPERTY(BlueprintReadWrite, Category = "MissileTest")
        FString key;
    UPROPERTY(BlueprintReadWrite, Category = "MissileTest")
        FString name;
    UPROPERTY(BlueprintReadWrite, Category = "MissileTest")
        FString type;
};
template<typename T>
void serialize(T& a, FMissile& in) {
    a(
        make_nvp("name", in.name),
        make_nvp("key", in.key),
        make_nvp("type", in.type)
    );
}

おわりに

UE4JSONを解釈するための、個人的BestWayでした。伊藤兎さんの記事にある通り、標準機能はBestではないためこちらを利用することをおすすめします。

今日から使えるim@sparql術

アイドルマスター Advent Calendar 2020 4日目の記事です。

はじめに

冬優子ーー!!!誕生日おめでとーーー!!!

はい。
明日はアイマスハッカソンです。ご準備~?

imas.connpass.com

というわけでですね、おそらく今日から準備をしている人に向けて、「今日から使えるim@sparql術」を紹介しようと思います。

sparql.crssnky.xyz

数式を使う

体表面積、考えたこと無いけど合ってるんすかね?
10,11,12行目のbind句とその中身が注目ポイントです。bind句はas句と一緒に使います。where句の中で関数の戻り値や他の変数を別の変数に代入する際に使います。
値 as ?変数名のように、左から右に流れるのは慣れないかもしれませんね...
中では四則演算やmath関数が使われています。

XQuery and XPath Functions and Operators Math Namespace Document

Using Math Functions with SPARQL — GraphDB Free 9.4.0 documentation

に多くの関数があるので、必要に応じて使っていきましょう。

述語を連結して使う

10行目のschema:member/rdfs:labelが注目ポイントです。ユニットに所属するメンバーのURIschema:memberで取得した後、そのURIを主語にしてrdfs:labelで名称を取得できます。これを使えば、

のように、簡単に平均身長を抜き出すこともできます。

他のエンドポイントと繋がる

なんたって、LinkedOpenDataですから。他のエンドポイントと繋がってこそです。
こちらは、とある魔術シリーズに関するエンドポイント「とあるSPARQL」とim@sparqlが繋がる例です。
7行目のSERVICE句が注目ポイントです。
ここで別のエンドポイントを指定することで、別のエンドポイントに対してクエリを送ることができます。その結果と元のエンドポイントのクエリを統合することで、複数のエンドポイントの結果を纏めることができます。

WikipediaからLODを作成するDBpedia(更新が2016年で止まってる...)や、LODをWiki化して人間とコンピュータの双方が参照可能なDBであるWikidataなど、多種多彩なLODが世の中にあるので、ぜひご活用ください。

クエリを探す

im@sparqlのトップページにあるExampleに、少しだけクエリ例があります。また、JavaScriptの例も載せていますのでぜひご参考に。

☆ピコピコプラネット☆SPACEにも、im@sparqlや他のエンドポイントのクエリがたくさん共有されています。先人の知恵をどんどん吸収していきましょう。

space.pikopikopla.net

おわりに

以上です。im@sparqlを活用して、素早くアイマスエンジニアリングを制作していきましょう!!