研究

矢上祭とSwitch

チョコです.

矢上祭,お疲れさまでした.

今年もぴょんぴょん(+)人気だったな,,,,思った以上に「面白い」,「ハマる」って感想いただけてすごくうれしかったです.

 

さて,ぴょんぴょんですが,去年のゲームジャムで3日で作ったにして結構人気があったシューティングゲーム.今年用に二人プレイできるようにしたのと,かわいいかわいいKCSちゃんモードを入れました.

3

図1:ぴょんぴょん+の宣伝図(宣伝してない)

このゲームを毎年プロジェクターを使って大画面でやるのが恒例なのですが,KCSは Oculusを買う金はあるのに 同じコントローラーを二つも持っていません.ではここで,「試しにNintendo SwitchさまのJoyconを使ってはどう」という発想に至ったわけです.

さっそくSwitchを借りて,やってみよう!と思ったわけですが,ここでとても重要な2ポイントがあります.

1.PCにはBluetoothで通信できる

2.UnityはJoyconをコントローラーとして認識できる

まさに神.2秒で移植できるじゃん.(1日かかりました)

(1ですが,Joyconの上にある小さいボタンを長押ししながらpairingをしないと認識できません.)

とりあえず,ボタンを軸登録することですね.なお,キーボードででも同じ操作ができるように,以下のような入力ラッパーを書きました.

public static bool jbt(int i, int j) {
    return Input.GetKey("joystick " + i.ToString() + " button " + j.ToString());
}
public static bool jump(int i) {
    return Input.GetKey("space") || jbt(i, 4);
}

リスト1:InputManager.csの一部

ボタンのIDはこんな感じですね.

httrhgtrh

図2:JoyconのボタンID

Bluetoothの登録順でjoystick 1, joystick 2, …で決まりますね.つまり,複数台Switch持ってれば(ry

 

最後に,Input.GetButtonDown(“Jump”)を全部InputManager.jumpに変えるだけですね.

 

あ,そう.あとは一人プレイ用に書いたガバスクリプトを二人プレイにしたときに発生したバグの塊を解消する作業ですね...

 

来年も出したいな,,,(卒業しなくていいの?)

完.

ジオメトリシェーダでファーシェーダを実装した話

こんにちは、mo-takusanです。
今回は題名の通りファーシェーダを実装しました。

https://kcs1959.jp/archives/1928/research/unity%E3%81%A7fur-shader

こちらの先輩の記事を見て私も実装してみようと思い、今回取り組んでみました。
またググってみると、unityでファーシェーダを実装している記事は多くあるのですが、ジオメトリシェーダを利用しているものが見当たらなかったため、今回はこれを利用したものにすることを目標としました。

完成図は図のようになります。左側が今回実装したファーシェーダになります。左右どちらの球も同じテクスチャを貼っているのですが、違いは一目瞭然ですね。

2018-09-16_11h12_28

なお、実装においてはこちらの記事を大いに参考にしました。
https://qiita.com/edo_m18/items/75db04f117355adcadbb

また、実装において利用したテクスチャは次のサイトから使わせて頂きました。
http://photoshopvip.net/25382

ファーシェーダとは

ファーシェーダとは、その名の通り毛並みのふわふわ感を表現するシェーダを指します。
ファーシェーダは主にシェル法やフィン法などの実装方法がありますが、今回はシェル法を用いていきます。

シェル法

シェル法においては毛並みを一本一本描画していくわけではなく、層状に毛の断面を描画していくことで、全体として毛並みのように表現する手法です。
具体的には、次のように行います。

  1. 各頂点に対してそれぞれの法線方向に一定距離だけ移動した頂点を生成し、元のメッシュより一回り大きいメッシュを生成する。
  2. メインテクスチャとは別に毛束の断面のようなテクスチャを用意し、そのテクスチャのRGB値が一定を超えたテクセルに対してのみメインテクスチャの色を乗せ、それ以外の部分は描画を行わないようにする。
  3. メインテクスチャを貼る閾値を少し大きくしていきながら、1.及び2.の操作をくり返す。

1.の操作をジオメトリシェーダで、2.の操作をフラグメントシェーダによって実装していきます。

先述のようにシェル法では毛を一本一本描画するわけではないため、層の数が十分でない時は毛束に見えません。以下の図に示すように層が目立ってしまうことが分かると思います。

2018-09-16_11h19_14

実装

それでは実装を示していきます。
先述のように、1.をジオメトリシェーダで、2.をフラグメントシェーダで実装します。

まずは1.です。

[maxvertexcount(81)] //これ以上多くの頂点を生成することはできない
void geom(triangle appdata input[3], inout TriangleStream outStream)
{
    const float spacing = 0.35;
    const int start = _Iterator * START;
    const int end = start + _Iterator;

    [unroll(27)]
    for(int x = start; x < end; x++)
    {       
        float shellPos = _ShellInterval * x;

        [unroll]
        for(int y = 0; y < 3; y++)
        {
            g2f o;

            appdata v = input[y];

            float3 forceDir = 0;
            float4 pos = v.vertex;

            //ここの値はなんでも良さそうなのでそのまま流用させて頂いた
            forceDir.x = sin(_Time.y + pos.x * 0.05) * 0.2;
            forceDir.y = cos(_Time.y * 0.7 + pos.y * 0.04) * 0.2;
            forceDir.z = sin(_Time.y * 0.7 + pos.y * 0.04) * 0.2;
            forceDir += _Gravity - _Inertia;

            float factor = pow(shellPos, 3.0);
                        
            float3 norm = v.normal;
            norm += forceDir * factor;
            norm = normalize(norm) * shellPos * spacing;

            pos.xyz += norm;
            pos.w = 1.0; 

            o.position = UnityObjectToClipPos(pos);

            o.uv = v.texcoord;

            TANGENT_SPACE_ROTATION;
            o.lightDir = normalize(mul(rotation, ObjSpaceLightDir(pos)));

            TRANSFER_VERTEX_TO_FRAGMENT(o);

            o.iter = x;

            outStream.Append(o);
        }
        outStream.RestartStrip();
    }
}

今回ジオメトリシェーダでは三角メッシュを受け取って三角メッシュを出力します。それぞれのメッシュは依存関係がないため、PointStreamの入出力でもよさそうですが、仕様上PointStreamで出力してしまうと、面を貼ってくれなくなってしまうため、このように記述するしかありません。
ちなみに、maxvertexcountが81になっていますが、これより大きい3の倍数でVaridation Errorになってしまうためです(maxvertexcountのリファレンスを読んだのですがこれに関する記述は見当たりませんでした)。この値はフラグメントシェーダに値を渡す構造体の大きさにも依存していたので、渡せるデータサイズの上限値があるのでしょう。

残りは先ほど提示したページの実装とほとんど同じものです。
異なる部分はライティングのためのものになりますが、今回の内容と直接の関係はないので割愛します。触りだけ説明すると、ライトの方向を計算し、ライト情報を適切にフラグメントシェーダに渡しています。
詳しくはこちらの記事をご覧ください。
https://qiita.com/edo_m18/items/21d3b37596da3fd4b32b#%E9%96%A2%E9%80%A3%E3%83%AA%E3%83%B3%E3%82%AF

2.についてもライティング以外は同様の処理です。違いといえばノーマルマップによるライティングを行っている程度です。

さて3.についてですが、先ほどmaxvertexcountの値が81だと述べましたが、これでは層の数が最大でも27層までとなってしまい、元々表現したかったフサフサ感が損なわれてしまいます。これでは本末転倒なので、今回の実装でも参考ページと同様に同じパスを何度も記述して層の量増しを行いました。
といっても一回のパスで27層描画できるので3つだけ同じパスを用意しました。

ジオメトリシェーダによる実装のメリット

ジオメトリシェーダを利用して実装を行うと、プラットフォームによっては動かない可能性があるため、望ましくないことも多々あります。しかしながら、ジオメトリシェーダによってファーシェーダを実装した場合、次のようなメリットが考えられます。

  • 全く同じパスを数十個書く必要がないためスマート
  • バッチ数を抑えられる
  • 層の数を可変にすることができる

特に、層を可変にできることでお好みのフサフサ具合を表現でき、非常に便利でしょう。バッチ数を抑えることで
パフォーマンスは改善されるのでしょうか?ジオメトリシェーダがどれほど重いか計測が面倒だったので言及しないことにします。

まとめ

ジオメトリシェーダを利用することで、比較的スマートにファーシェーダを実装することができました。シェーダはすぐにビジュアルに表れるので実装していてとても楽しいですね!

UnityでのDeferred Celシェーディング

どうも,チョコです.院試おつ↓かれ↑ーい.

いつものUnityでのCelシェーディングをやっていました.しかし,シェーダを全部Cel式に変えるのはめんどい.そしてunlit shaderで照明を扱うのはどうも釈然としない.そこで,Deferredでなんとかならない?と思ったわけです.

UnityではDeferredの内部シェーダを変えられるようになっています.このように.

(Edit->Project Settings->Graphics)

Screenshot (13)

ここに自分のシェーダを突っ込めば,カメラの出力を制御できるというわけですね.

さて,これをやるにはまずbuiltin_shadersアセットをダウンロードしないといけない(ダウンロードページにあります).そして,Internal-DeferredShading.shaderを見つけます.

シェーダを中を見ると,おっと,この部分は画面に色を吐いているなと,読めばわかると思います.

half4 CalculateLight (unity_v2f_deferred i)
{
    ...
    half4 res = UNITY_BRDF_PBS (data.diffuseColor, data.specularColor, oneMinusReflectivity, data.smoothness, data.normalWorld, -eyeVec, light, ind);
    return res;
}

なるほど.つまり,ここの戻り値を変えればいいと.さて,Celシェーディングでやりたいことを確認しましょう.

deftoon

図の通り,まずは白の材質に対しての照明を得て(1),そしてCel風のカーブにし(2),最後にDiffuseを適用(3)すればいいです.上のコードを書き換えましょう.

uniform float _deferred_cutoff;
uniform float _deferred_shade;
uniform float _deferred_saturate;
half4 CalculateLight (unity_v2f_deferred i)
{
    ...
    half4 inten = UNITY_BRDF_PBS (half3(1,1,1), half3(0, 0, 0), 1, 0.5, data.normalWorld, -eyeVec, light, ind);
    float brg = clamp(ceil(inten.r - _deferred_cutoff), 0, 1);
    float shd = 1-((1-_deferred_shade) * (1-data.smoothness));
    return half4(saturate(data.diffuseColor * (brg * (1-shd) + shd), 1 + _deferred_saturate - (_deferred_saturate) * brg), 1);
}

(デフォルトシェーダの仕組みはどこにも書いていないので,関数の意味などはCGIncludesの中身を自分で読まないといけませんね)

はい.ここで,UNITY_BRDF_PBS は(1)なので,それを(2)にしたのがbrgとなって,最後にdata.diffuseColorを適用しました(3).

最後に,Inspectorでデフォルトのシェーダを変えよう.そしたら(エラーがなければ)オブジェクトのマテリアルを一切触っていないのにカメラの出力が変わります.

Screenshot (12)

これで1つのシェーダでアニメ風にできますね.スタイル変換捗りー.

(実はこの方法は,照明ごとに行われるので,光が重なるととても明るくなります.解決したらパーツ2の記事にします)

では.

ブルースカイ・カタストロフィ

ブルースカイ・カタストロフィ(つよそう)

スクリーンショット 2018-05-05 17.10.41

↑は参考にあった Blue sky orbit in the Gavrilov-A. Shilnikov model でパラメータも同じもの.

以下は, \(\varepsilon\) をそのまま固定しながら, \(\mu\) を \([0.1, 1.1]\) の範囲で動かしたもの(0.02 間隔で 80000 回のルンゲクッタ.最初の 1000 回は捨てている).

OpenCVでカメラキャリブレーション

OpenCVを使ったカメラキャリブレーションをググると,まずCでの実装例が出てきて,次に比較的新しいpythonでの実装例が出てくるが,C++での実装例がいまいちヒットしない.

加えて,カメラキャリブレーションは基本的にあらかじめ用意したデータについて行うが,私は普段Webカメラを利用するので,データの収集とキャリブレーションを同時にできるといいな,というのがあった.

ので,作った.

リポジトリはこっち
https://github.com/Lait-au-Cafe/calibration

本当はできるだけシンプルにしたかったのだが,冒頭で述べたようにプリセットのデータがなくてもできるようにしつつ,でもプリセットのデータがあってもできる,という仕様にした結果少し複雑になってしまったように思う.

当該リポジトリを利用する際にはビルドにOpenCV3.xとpkg-configが必要なのに注意.

P行列の自由度とパラメータ

物の本によると,カメラによる物体の投影を表現する “P行列” は以下のようにあらわされる.

PMat1

なるほどな.

別の本では以下のように記述されている.

PMat2

まあそういうこともあるだろう.

ところで,P行列の自由度(DOF, Degree of Freedom)は一般に11とされる.
P行列は全部まとめると3×4行列になるが,定数倍しても意味が変わらないのでここから1を引いて11,という説明がされているのを見かける.

さて,上の二つの式をもう一度見てみよう.
回転行列Rと並進ベクトルtは二つの式で共通で,自由度はともに3であるから,一番左の行列だけで自由度は3+3=6.
真ん中の行列は焦点距離fがあって自由度1.
左の行列は,上の式では変数がa, s, c_x, c_yの4つで自由度4.
下の式では変数がδ_x, δ_y, c_x, c_yの4つで自由度4.

上の式も下の式も全部合わせて4+1+6=11自由度!
世界は今日も平和だなぁ…





ほんまか???

上の式と下の式で異なる点は以下の二点である.

  • 上の式ではx軸方向のスキューsが考慮されている.
  • 上の式ではアスペクト比aで表しているものを,下の式ではピクセルの物理的なサイズδ_x, δ_yで表している.

これを見て私が抱いた疑問が以下の2点.

  • 上の式でもaではなく物理的なサイズδ_x, δ_yで表せば自由度が12になる??
  • さらにy軸方向のスキューも考慮すれば自由度が13になる???

式にするとこんな感じ.

PMat3

しかし自由度12はギリギリ許容できても,3×4行列の自由度が13になることは逆立ちしてもあり得ない.
ではどれが正しくてどれがどう間違っているのか.

順に確かめていこう.

アスペクト比aとピクセルの物理的なサイズδ_x, δ_yについて



結論
“焦点距離f”と”アスペクト比a”のペアで表すか,”ピクセルの(相対的な)物理的サイズδ_x, δ_y”で表すのが冗長の無い表現である.

先程のP行列の式で,下の方の式では焦点距離fとピクセルの物理的なサイズδ_x, δ_yを用いてP行列を表現していた.
これは解釈上はいいのだが,自由度の観点ではこのうちの一つは冗長なので誤解を生じやすい.
変数はf, δ_x, δ_yの三つあるが,実際には自由度は2しかない.

式的な解釈としては,先ほどの式を少し変形して以下の形にするとわかる

PMat4

ここの式を見ると,1/δ_x’=f/δ_x, 1/δ_y’=f/δ_yと置き直しても普遍性を失わないことがわかる.
よって,スキューを考えない場合P行列の自由度は10.
あるいはf’=f/δ_x, a=δ_x/δ_yと置きなおすと,焦点距離とアスペクト比で表現できる.

f, δ_x, δ_yの変数のうち一つが不要である理由を言葉で表現するとどうなるか.
ここでもう一度焦点距離fの意味について問い直すと,これはカメラ座標系のスケールを正規化するためのパラメータとして解釈できる.
焦点距離fによる正規化を行った後,再度ピクセルの物理的なサイズδ_x, δ_yを用いてスケーリングを行うのだが,別に一度正規化を挟まずとも直接,カメラ座標系のスケールに対するピクセルの物理的なサイズδ_x’, δ_y’によってスケーリングしてしまえばそれでよい.
わざわざ一度fでスケーリングを行う必要はない.
(もちろん,処理に物理的な解釈を与えるという観点では重要な操作である).

もしスキューを考慮しないP行列で自由度が11になると説明する人間が居たら「ほんまか??」をぶつけよう.

y軸方向のスキューについて

結論
y軸方向のスキューは回転R,並進t,焦点距離f,アスペクト比aを取り直すことで消えるので考慮しなくてもよい.仮にy軸方向のスキューを明示的にP行列の式に組み込んでも自由度は変わらず11となる.

証明は以下.

PMat5

かなり雑に言葉で説明すると,カメラを90度回転させればx軸方向のスキューがy軸方向のスキューになる,という感じ.

画像作り終えてからsinの符号が逆なのに気づいた….
眠い…,適宜読み替えて読んでください….

まとめ

P行列の自由度は,
焦点距離f + アスペクト比a + スキューs + 画像中心の座標c_x, c_y
+ カメラの回転R(3自由度) + カメラの並進t(3自由度)= 11自由度.

以上.

OpenCL with OpenCV (OpenCV-CL)を使ってみた.-RGB編-

前回は取得したフレームをcvtColorでグレー画像に変換してからOpenCL側へ渡す,というまどろっこしいことをしていましたが,実際カラー画像を扱えないとお話にならないので何とか使えないかと試行錯誤.

CUDAの場合はuchar3は構造体として実装されているようで[要出典],uchar(=グレー画像)の場合とほとんど同様に扱うことができるが,OpenCLのuchar3は少し違った仕様になっているようで,ucharの場合をそのまま拡張しただけではうまくいかない.(CUDAのコードも適当に整理して上げたいですね).

ucharなどをスカラ型と呼ぶのに対し,uchar3などはベクタ型と呼ばれますが,このベクタ型の配列にアクセスする場合はvloadnやvstorenを使う.

参考サイト
How vector pointers work in openCL
Vector Data Load and Store Functions

それを考慮して実際にRGB画像を扱って各要素にアクセスした例が以下.

やっていることは至極単純なグレースケール化のみ.
今回もよくわかっていない点として,widthがいつでもUMatのpitchと等しくなるのか,という点.
例えば,CUDAの場合はx+y * widthとやるとうまくいかなくて,x+y * pitchのようにしなければいけない.つまり要素数はwidth分だが,各行当たりのメモリはもう少し余裕をもって確保されている.このpitchの値はcudaMallocPitchでメモリをアロケートする際に一緒にもらえる.
今回のOpenCV-CLの場合はOpenCV側の提供するUMatを使っているため問題ないのだろうか.
一応UMatもプロパティとしてstepやoffsetを持っているため,これを考慮せずにindexingしても大丈夫なんだろうかいやでも今のところうまくいってるしなあ,という感じ.
つまるところ,まだまだ検証の足りないコードなのでindexing周りで不具合が生じる可能性がある.

ちなみにindexingまわりで不具合があると出力画像はこんな風になりがち.
DXsiYnIVwAAS8bV

今日は以上.

OpenCL with OpenCV (OpenCV-CL)を使ってみた.

ここに “””つらみ””” があります.

image

環境を統一しようにもなかなか険しいものがある.(NvidiaのOpenCLはCUDAのドライバ入れれば動く…?)
世界に試されている.
でも今出先なので(=Geforceを積んでいるデスクトップ環境が使えないので),ノートPC上でできる環境を適当に決めて実装しないと無限に「グレブナ基底と代数多様体入門Ⅰ」を読んでしまう.無限に某ーロッパ企画のゲームをプレイする某員長の動画を見てしまう.

色々と考えた結果,OpenCVの環境作ればOpenCLが使えるらしいことを知って,じゃあこのOpenCL使ったらいいか,という気持ちになった.
OpenCVは全体的にドキュメンテーションに難があってほとんど参考にならないが,神先駆者様がいたのでこれをほとんどコピペでとりあえずサンプルコードを動かしてみた.

negaposi

とりあえずサンプルは動いたが今後手を加えていくとうまくいかなくなるかもしれないのでしばらく様子見.
カーネルコードをロードしてコンパイルするあたりでRustのシャドーイングを使いたくなったが残念ながらこれはC++なのでそうは問屋が卸さない.
世界中のスクリプトがすべてRustに置き換わらないかな.
せめて世界中の言語がすべて強い静的型付き言語にならないかな.

RustからC++を呼び出すこともなんとなく考えたが,参考サイトに
“C++ exceptions can mostly be caught in D, but that’s not a thing in Rust at all. “
とあって,確かになぁ…という気持ちになった.
ただでさえセーフな言語からアンセーフな言語を呼び出すのは厳しいのに,エラーハンドリングのやり方などの言語仕様も異なるとなると,考えることが増えそう(曖昧).

コードの印象としては,カーネルコードのロード,コンパイル,呼び出しの流れはPyOpenCLのほうが若干すっきりしていた気がする.(以前書いたPyOpenCLではホストコード中にカーネルコードを書いていたのに対し,今回は別ファイルにカーネルコードを書いているため,ファイルを読み込む処理が追加されているため煩雑に感じるのかもしれない).
カーネルコードの引数指定の部分は知らないと絶対にわからない仕様(詳しくは参考サイト様参照)なのにドキュメンテーションには記載が見当たらなかったので,このあたり敷居が高いなと感じた.

今回のコードで少し不思議に感じたのは,フレームのグレースケール画像(gray)が更新されたときにデバイスのバッファ(d_frame)へデータを送らなくてもちゃんと更新が反映された点.UMatは今回の例のように直接imshowに渡せるようだし,情報の受け渡しはOpenCV側がやってくれているのだろう.
つまり,cv::UMat d_frame = gray.getUMat(…);が実行された時点で,grayへの書き込みが自動的にd_frameに反映されるようにお膳立てしてくれているのかもしれない.(というかそもそも実体がGPU上に移るのかもしれない).
確信はないけど.

とりあえず今日はここまで.

参考サイト様
OpenCV 3.0.0での独自カーネルOpenCL
UMatの内部処理(OpenCL編)
Any updates on calling C++ from Rust

unityで外部テキストをC#コードとして読み込む

こんにちは。mo-takusanです。

今まではほとんど記事を書いてこなかったのですが、さすがにそろそろ投稿していこうと思います。

unityで外部コードを読み込むには…

最近とある事情でコンパイル後に外部ソースコードを読み込みたい、という場面がありました。

「あああ、Python書くかぁ」

となっていたのですが、念のため調べると、C#はコンパイル言語ですが、ランタイムでコンパイルができるようです。C#神!!やっぱり.NET最強!!!

ただし、untiyとの相性が悪いものが多く、四苦八苦してしたので、紆余曲折の様子を記事にしていきます。

なお、本記事で使用したunityのバージョンは2017.1.1f1です。

まずはできた方法を、、

まあ、とにかく知りたいのは実際にうまくいったやり方でしょう(需要があれば)から、その方法から話していきます。

なんだかんだとググっていくうちに以下のGitHubにたどり着きました。

https://github.com/aeroson/mcs-ICodeCompiler

このサイトを見たとき、ついに来た!最終コミットもそれなりに新しいしこれはいけるやろ!と思ったのですが、ここからが長かった…(unityのバージョンを合わせればよかったとかそういうツッコミはなしでお願いします、、、)

2018-02-07_23h38_41

早速クローンしてサンプルプロジェクトを開いてみると…

2018-02-07_23h42_07

地獄絵図…。unityはICodeCompilerやCompilerResultsが存在していないと主張してくるのですが、

https://msdn.microsoft.com/ja-jp/library/system.codedom.compiler.icodecompiler(v=vs.110).aspx

https://msdn.microsoft.com/ja-jp/library/system.codedom.compiler.compilerresults(v=vs.110).aspx

のように、System.CodeDom.Compiler名前空間には確かに存在しています。実際コードの方でもusingされており問題はなさそうです。やけくそで丁寧に書き直してみても全然ダメ…

2018-02-07_23h45_47

うーーーん。

これについては解決方法が全く分かりませんでした。ので、ダメもとで一緒にクローンしてきた「non Unity3D usage」のコードを新規プロジェクトに入れてみました。dllはPluginsに入れることを忘れずに…

2018-02-08_00h03_29

おや?エラーが出ない!
やった…やったよ、、おれ、ついにやってのけたよ…
そうするとデモが動かなかった理由がいよいよ謎ですね。

それはともかくとして、あとは適切にファイルを読み込むコードを書いて、、、

 private static Assembly Compile(IEnumerable&lt;FileInfo&gt; files)<br />
 {<br />
     var domain = AppDomain.CurrentDomain;<br />
     var references = domain.GetAssemblies().Select(a =&gt; a.Location).ToArray();<br />
     var options = new CompilerParameters<br />
     {<br />
         GenerateExecutable = false,<br />
         GenerateInMemory = true,<br />
     };<br />
     options.ReferencedAssemblies.AddRange(references);<br />
     var compiler = new CodeCompiler();<br />
     var result = compiler.CompileAssemblyFromFileBatch(options, files.Select(f =&gt; f.FullName).ToArray());<br />
     return result.Errors.Count &gt; 0 ? null : result.CompiledAssembly;<br />
 }

完成しました!!!
なお、こちらのプロジェクトは諸事情で公開していないのであしからず。

ここからはできなかったことを書くぞ!

と言いましたが、疲れたので失敗の様子はダイジェストでどうぞ

System.CodeDom.Compilerを素で使う

なぜかコンパイルすると動かない(unityではよくある泣)

AssetStoreからダウンロード

https://assetstore.unity.com/packages/tools/cs-script-for-unity-23510

このページにいい感じのアセットがあったのでダウンロード。が、だめ。(古かった)

Roslynを使う

unityが.NET4.6に対応したことを利用して、次のサイトを参考にして組んでみよう!

https://www.gaprot.jp/pickup/tips/roslyn

unityが反応してくれない!おい!!nugetからdll落としてPluginsに入れてもダメでした。(むしろそれ以外を知りませんが)

ローレンツアトラクタとカオス

こんにちは.TRSasasusu です.

記事を更新していないだけで,KCS は活動しています.新歓の準備も進んでいるようです.

さて,自分は生命情報学科に所属していますが,この前のレポートにてカオスで遊んだので,今回はその話をします.

スクリーンショット 2018-02-01 15.46.11

これはローレンツ方程式(↓の式)のアトラクタです.この軌道に沿って点が移動していきます.


\begin{align}
\frac{dx}{dt} &= -\sigma x + \sigma y \\
\frac{dy}{dt} &= -xz + rx -y \\
\frac{dz}{dt} &= xy – bz
\end{align}

特にこのようなフラクタル構造を持つアトラクタはストレンジアトラクタと呼ばれ,カオスを生み出します.蝶の羽みたいで美しいですね.

そして,パラメータ(今回は \(\sigma,\ r,\ b\))を変化させると,カオスになったりならなかったりします.これを表すのが分岐図です.

スクリーンショット 2018-02-01 16.07.43

なんかすごいですね.そして,カオスを定量的に表すのがリアプノフ指数(多次元でまとめたものがリアプノフスペクトラム)です.力学系を表すヤコビ行列を時系列順に並べて QR 分解して(時刻 \(0\) では時刻 \(0\) のヤコビ行列のみを,それ以降ではヤコビ行列に前時刻の \(Q\) を右から掛けたものをそれぞれ QR 分解する),各時刻の \(R\) のそれぞれの対角要素の \(\log\) をとって全部足し合わせて \(N\) で割ると,以下のようになります.

スクリーンショット 2018-02-02 1.06.55

1 つでも正のリアプノフ指数があればカオスとなるようなので,この結果は分岐図のものと一致していますね.

最後に,ストレンジアトラクタの動画を載せて終わりにします(動画はレポートには載せられない).