GPUを使ってPDFのパスワードを解析する(Google Colab編)

以前ローカル環境でGPUを使ってPDFのパスワード解析してみたが、
実は、Google Colabを使えば、高性能GPU搭載PCを持っていなくても、GPUを使った解析を体験できてしまう。
ローカルよりも環境構築がとても楽なので、GPGPUの速度を手っ取り早く体感したい方におすすめ。
前記事同様、悪用厳禁。暗号化PDFは自分で検証用に準備すること。

準備するもの

ブラウザが開けるPC(chrome bookでもok)

環境構築

  1. ブラウザでGoogle Colabを開く。
  1. ヘッダーメニューのファイル→新規作成をクリック。
  2. ヘッダーメニューのランタイム→ランタイムのタイプを変更→GPUを選択。
  3. 以下をコードセルにペースト、実行するとHashcatが導入できる。
    1
    !apt install cmake build-essential -y && apt install checkinstall git -y && git clone https://github.com/hashcat/hashcat.git && cd hashcat && git submodule update --init && make && make install

検証

今回はGPGPUの速度を手っ取り早く体感するのが目的であるため、ハッシュの抽出にWebサービスを利用する。
以下のサイトに暗号化PDFをアップロード。



ハッシュをコピーしてtxt形式で保存。




ハッシュが保存してあるtxtファイルをGoogle Colabにアップロード。




新しいコードセルを作成し、Hashcatを実行する。ColabではUnixコマンドは頭に!をつける必要がある。
例えば、

1
! hashcat -m 10500 -a 3 -w 4 hash.txt '?d?d?d?d?d?d'

-w 4 を付けることで全力で探索することができる。以前ローカル環境で-w 4をつけたらクラッシュしたが、Colabでは正常に動いた。
詳しい使い方は以下のサイトやWikiを参照。




Google ColabではGPUは3種類(K80 T4 V100)あり自動で割り振られる。今回は、中くらいの性能であるT4が割り当てられた。(性能順は K80 < T4 < V100)
解析速度を見てみると12000kH/s~16000kH/sであり、ローカルの2070sとほぼ変わらない速度であった…
運よくV100が割り当てられたら、更に早くなるに違いない。
この環境を無料で使えてしまうGoogle Colab恐るべし…

GPUを使ってPDFのパスワードを解析する

オンライン授業やリモートワークでパスワード付きのPDFを扱うことが増えてきたと思う。
適切な強いパスワードを設定する人もいると思うが、大多数はパスワードを適当に設定しているだろう。
今回パスワード解析ツールHashcatとGPUを用いてPDFのパスワードを解析してみる。
実際に解析することで、どのようなパスワードが強いか、検証する。
悪用厳禁。

準備するもの

  • グラボ付きPC
    • 検証で使用したPCのスペック
      • CPU: i7 8700
      • GPU: 2070 super
      • RAM: DDR4-2400 24GB

環境構築

今回、Windows 10 home (1909)環境下で行った。一部WSLを使用している。
Hashcatをソースコードからビルドしないといけないため、パッケージ提供のあるUbuntuや、デフォルトツールとして導入済みのKali Linuxを用いた方が楽かも。
Windows ver2004だとWSL2上でCUDAが使えるので、Windows環境下であればWSL2上でKaliを使うのが一番楽かな?

CUDA Toolkitの導入

CUDAToolkit 9.0以降を導入する。
古いCUDAToolkitが入っている人は、一度アンインストールしてから、新しいToolkitを導入しよう。
異なるバージョンのToolkitが複数あると正常に動かなかった。

Jown the ripperの導入

PDFからハッシュを抜き出すために使う。
64-bit Windows binariesをDLして解凍。pdf2john.plを用いる。

Hashcatの導入

ハッシュ文(暗号文)が分かれば、PDF MSOffice ZIP ありとあらゆるファイルのパスワードを解析できるちょっと怖いツール。
使い慣れている人が脆弱性を利用して、計算量を削減して実行すると、22.7ゼッタ(1垓)ハッシュ毎秒というとんでもないスピードで解析も可能。


今回Windows環境下で使うので、公式サイト若しくはgithubからソースコードをDLしてビルドする。gitcloneしてもいい。

WSL上でビルドするためMinGWを導入。

1
$ sudo apt install  mingw-w64 win-iconv-mingw-w64-dev

エディタでHashcatフォルダ内のsrc/Makefileを開く。


573行目のopt/win-iconv-64を/usr/x86_64-w64-mingw32にパス変更。
ビルドする。

1
$ make win -j 5

hashcat.exeができる。

解析作業

環境構築が終わったので、実際に解析してみよう。

ハッシュの抽出

John the Ripperのpdf2john.plを使う。
WSLにはperl実行環境はデフォルトでインストールされていると思うので、WSL上で実行。

1
$ Perl john-1.9.0-jumbo-1-win64/run/pdf2john.pl MyPDF.pdf > MyPDF-Hash.txt

MyPDF.pdfには解析したいPDFのパスを入力、MyPDF-Hash.txtに抽出したハッシュが保存される。

John the Ripperの代わりにハッシュ抽出サイトを使ってもよいが、大切なファイルはアップロードしない方がいいかも。

Hashcatで解析

WSLではなくcmdでhashcat.exeを実行する。
例えば

1
C:/Users/user/hashcat>hashcat.exe -m 10500 -a 3 -w 4 C:/Users/user/Desktop/Mypdf-Hash.txt

のように入力。

-mオプションで、適切なハッシュを選択。

番号 対象
10400 PDF 1.1 - 1.3 (Acrobat 2 - 4)
10500 PDF 1.4 - 1.6 (Acrobat 5 - 8)
10600 PDF 1.7 Level 3 (Acrobat 9)
10700 PDF 1.7 Level 8 (Acrobat 10 - 11)

-aオプションでアタックモード選択。

オプション モード
0 辞書攻撃
1 辞書組み合わせ
3 総当たり攻撃
6 辞書+マスク(ハイブリッド攻撃)
7 マスク+辞書(ハイブリッド攻撃)

詳しい使い方は、wikiや下のサイトを参照。

結果

今回Acrobatの有料版を持っていなかったため、MSWordからパスワード付きpdfを作成した。
ハッシュを見た感じ128bitAESであったため、PDF1.6だと思われる。
最新のPDF、Acrobat9以降(PDF1.7)では256bitAESが標準であるため、PDF1.6よりも解析難易度は高いと思われる。

数字6桁総当たり攻撃

pass:324913
数字6桁だと100万通り。
1秒以下で解析できた。
速度が14687.6kH/s=1468.7万回/sなので当たり前かな…
数字8桁でも1億通りなので、10秒かからないと思われる。


小文字英語数字6桁総当たり攻撃

pass:gewr39
今度は(26+10)^6=2176782336通り
2分くらいだと思われる。
実際は30秒で解析できた。


小文字英語数字8桁総当たり攻撃

pass:hoge1200
36^8=2.28兆通り。
ちょっと厳しいかなー
全て探索が終わるまで1日と13時間かかるが…
まさかの1分45秒で解析できてしまった…
総当たりなので、前半で当たれば解析は可能。


大文字小文字英語数字8桁総当たり攻撃

pass:Hksg1532
62^8=218兆通り。
全て探索が終わるまで117日かかるので、少し絞ってみる。
大文字小文字英語と数字をつかって8桁というのはよく使われるパスワードだが、1文字目を大文字にする人が多いだろう。
1文字目のみ大文字、2~8文字目は小文字英語数字と絞り込んでみると117日を27時間まで減らすことができた。
さらに絞り込んで、1文字目は大文字英語、2~4文字目小文字英語、5~8文字目を数字と仮定して総当たりしてみる。これにより、3分まで減らすことができた。
実際、30秒程度で解析できた。


大文字小文字英語数字記号8桁総当たり攻撃

6634兆通り。



全て探索が終わるまで10年47日かかるらしい。現実的な時間では総当たりでの解析は不可能。
最近記号を含めないとパスワード登録できないサービスが増えたが、脆弱性がない限り、理にかなっていることが分かる。

まとめ

今回誰でも手軽に手に入れることができる2070superで解析してみたが、小文字英語数字8桁程度なら、総当たりでも現実的な時間で解析できることが分かった。
従ってtesla v100等、最新のgpgpu専用gpuを複数台使用したら、更に早く解析できると思われる。
また、hashcatには、辞書列攻撃と総当たり攻撃を組み合わせたハイブリット攻撃が可能である。これを利用すると8文字以上のパスワードの解析可能性が大幅に向上すると思われる。
例えば、power1342というパスワードで、powerという単語が辞書に含まれていたら、数字4桁総当たり攻撃とほぼ変わらない速度で解析ができる。従って、8文字以上でも単語と適当な数字の組み合わせでは強いパスワードとは言えない。
辞書列攻撃が不可能なランダム文字列で、大文字小文字英語数字記号を含む8桁以上がやはり強いパスワードと言える。

WSLで「12ステップで作る組み込みOS自作入門」の環境構築をしてHello World!してみる

暇なので積読していた「12ステップで作る組み込みOS自作入門」に手を出してみました。
書籍に紹介されていたwindowsでの開発環境ではCygwinの使用が推奨されていましたが、今はWSLがあるのでこれを使ってみようと思いました。
WSLはおろかLinux自体まともに使ったことがなかったので、環境構築に丸一日かかった…

モノの準備

とりあえず、自分の環境の紹介から。

  • デスクトップPC(Win10pro 1903 64bitに WSLでUbuntu 18.04.4LTS導入済み)

次にマイコン関連

ボードのシリアルポートとケーブルを固定する金属部分が、邪魔で接続できないので外しました。



私は、問題なく書き込みできましたが、公式ページでは延長ケーブルを買って、ねじ止めして接続することが推奨されています。

環境構築

WSL導入済みという前提のもとで書きます。
折角、ネイティブLinuxではなくWSLを使うので、ファイル編集とシリアル通信テストはWindows側から行ってみます。
エディタはVSCode、シリアル通信テスタはSeristerを使用します。

一応、自分が構築したディレクトリ構造を記します。(gccなどのコンパイラとコードはディレクトリ分けてもいいかも)

1
2
3
4
5
6
7
8
9
10
home
|---user
| |---12step
| |---src
| |---binutils-2.19.1
| |---gcc-3.4.6
| |---kz_h8write-v0.2.1
| |---01 (以下書籍のコード)
| |---02
| |---

今回、gcc、binutilsのconfigureスクリプト実行時に、ファイル場所を指定しません。その場合、h8マイコンのツール類(h8300-elf-hoge)は、make install時に以下にインストールされます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Ubuntu
|---bin
|---boot
|---dev
|---etc
|---home
| |---user
| |---12step
| |---src
|---usr
| |---local
| |---bin
| |---h8300-elf-gcc
| |---h8300-elf-as
| |---
| |---

binutils

初めにbinutilsを導入します。

バージョンは2.19.1を選択。最新のバージョン入れたらビルド時エラーはいたので書籍に掲載されているバージョンをお勧めします。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cd ~/ 
$ mkdir 12step
$ cd 12step
$ mkdir src
$ cd src
$ wget http://core.ring.gr.jp/pub/GNU/binutils/binutils-2.19.1.tar.gz
$ tar zxvf binutils-2.19.1.tar.gz
$ cd binutils-2.19.1
$ mkdir build
$ cd build
$ ../configure --target=h8300-elf --disable-nls --disable-werror
$ make
$ sudo make install

gcc

次にgccを導入します。
バージョンは3.4.6を選択。こちらも書籍と同じバージョンをお勧めします。

今回、64bit環境ですので、パッチの適応が必要です。

1
2
3
4
5
6
7
8
9
10
11
12
$ cd ~/12step/src
$ wget http://core.ring.gr.jp/pub/GNU/gcc/gcc-3.4.6/gcc-3.4.6.tar.gz
$ tar zxvf gcc-3.4.6.tar.gz
$ cd gcc-3.4.6
$ vi gcc/collect2.c /* 本で解説されている修正を行う */
$ wget http://kozos.jp/books/makeos/patch-gcc-3.4.6-x64-h8300.txt
$ patch -p0 < patch-gcc-3.4.6-x64-h8300.txt /* 64bit環境用のパッチを適用 */
$ mkdir build
$ cd build
$ ../configure --target=h8300-elf --disable-nls --disable-threads --disable-shared --enable-languages=c --disable-werror
$ make -j 5
$ sudo make install

書籍p17の修正は上記のようにviを使用してもいいですが、Windows側から編集してみましょう。


エクスプローラーを開き、アドレスバーに\\wsl$と入力



WSLにアクセスできました。


gccディレクトリで右クリックしてCodeで開くを選択




vscodeで編集ができます。



kz_h8write

シリアル通信でH8/3069FのフラッシュROMに書き込みを行うツールです。h8writeの改良版とのことでこちらを使用します。

  • H8/3069F writer for KOZOS (kz_h8write)
    zip形式での配布のため上記サイトからだとwgetコマンドが使えません。試してみたところhtmlがダウンロードされてしまいました。
    そこで、Windows側でブラウザからkz_h8write-v0.2.1.zipをダウンロードし、解凍、エクスプローラーを開きWSLの該当ディレクトリにコピーします。

    コピー出来たら以下のようにコマンドを打ちます。
    1
    2
    $ cd ~/12step/src/kz_h8write-v0.2.1/PackageFiles/src
    $ make
    kz_h8write というバイナリがビルドされブートローダーが生成されます。
    これは書き込み時に、プロジェクトのMakefileから直接参照させるのでmake installする必要はないです。

    とりあえず、環境構築は出来ました。
    次にHello World!してみます。

Hello World!

まず、公式サイトからソースコードをダウンロードします。

01というフォルダが、Hello World!のプロジェクトだと思います。
このフォルダを先ほどと同じように、エクスプローラーからWSLにアクセスして、作業ディレクトリにコピーします。

次に、プロジェクト内のMakefileを編集します。




16行目20行目を書き換えます。



16行目は上記のように書き換えればいいですが、20行目は、シリアルポート接続先なので、環境によって異なります。
Windows 10 のアップデートBuild 16176でWSLから直接シリアルポートを利用できるようになりました。

  • Serial Support on the Windows Subsystem for Linux

    デバイスマネージャーからマイコンで使用しているシリアルポートを確認します。



    COM1なら/dev/ttyS1
    COM2なら/dev/ttyS2
    と指定します。

    上記の場合COM3なので/dev/ttyS3と指定します。

    後は書籍通り

    1
    2
    3
    4
    $ cd ~/12step/src/01/bootload
    $ make
    $ make image
    $ make write

    と打てば書き込めると思います。書き込めない場合、マイコンのスイッチをチェックしてみてください。

    最後にseristerで監視してみようと思います。

    マイコンのスイッチを切り替えた後、書籍に書いてありますが、ボーレートを9600、バリティなし、バイトサイズ8、ストップビット1と設定します。
    ポート番号は先ほどデバイスマネージャーで確認したポート番号を入力してください。

    監視開始ボタンを押し、マイコンボードのリセットボタンを押すと以下のように、Hello World!が出力されると思います。



  • 注意
    Seristerの監視をオンにしたままマイコンに書き込むとエラーが出るので、書き込む際にはSeristerの監視をオフにしましょう。

processingでマンデルブロ集合を書く

春休みがクソ長くなったので、とりあえず何かしようと思った。
みんな大好きマンデルブロ集合をprocessingで書いてみる。

マンデルブロ集合とは何か

説明しようと思ったけど、なんかhexoでtex書くとバグるのでやめた。

※参考リンク

マンデルブロー集合 ——2次関数の複素力学系入門——: 川平 友規 名古屋大学大学院多元数理科学研究科

マンデルブロ集合の不思議な世界

ソースコード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//漸化式計算回数 
int N = 255;
// 拡大率
float SCALE = 3.0;

void setup() {
size(512, 512);
}

void draw() {

//中心に原点配置
translate(width/2, height/2);
background(0);

for (int i = -width/2; i <= width/2; i++ ) {
for (int j = -height/2; j <= height/2; j++ ) {
// 複素数c=x+yiを定める
float x = SCALE * i / width;
float y = SCALE * j / height;
//収束判定
int r = calc(x, y);

//収束したら黒
if(r == 0){
stroke(0, 0, 0);
//点を描写
rect(i, j, 1, 1);
}
else{
// 発散の速度に応じて色を指定
stroke(r % 256 + 1, r % 16 * 16 + 1, (r % 32) * 8 + 1);
//点を描写
rect(i, j, 1, 1);
}
}

結果

UnityとKinectで作るジェネレーティブアート:Part1

今更感あるけど、
今年の学祭(去年になっちゃったね)で展示したものの紹介。

サークルの備品でほこりかぶってた Kinect をどうにか活用できないかなと思って、手を付けたが、初代 Kinect(v1)であったため情報が少なく、レポート等で忙しく(言い訳)、結局 2 週間程度で無理やり形に持って行った。完成度は高いとはあまり言えないのであしからず。

最初ゲームを作ろうと思ったが、なぜか当たり判定が死んで、半日程度格闘したが原因がわからなかったので別のものを作ろうと考えた。サークルの出し物がデザイン寄りなのも考えて、ジェネラティブアート的なのを作ろうと思った。

「Unity ジェネラティブアート」でググると一番上にこのサイトが出てくる。

https://ics.media/entry/19479/

これを Kinect で制御したらまあまあ面白いものができるのではと思った。

描写に関しては上のサイトとほとんど同じ…だとつまらないので、いくつかモードを追加した。

Kinect の前に人がいないとき、キャンパスに説明などを描写する待機モード。



上のサイトをもとに作った、描写モード 1。




自作した、花火みたいなエフェクトを表示させる描写モード 2。

簡単に説明すると、Kinect が人を認識していないとき待機モードになる。

人を認識すると描写モードに遷移する。現在時刻が 0-19 分の時、描写モード 1 を表示。現在時刻が 20-59 分の時、描写モード 2 を表示する。
例えば 17:09 の時、描写モード 1 を表示。10:34 の時、描写モード 2 を表示する。

描写モード 1 では、左腕の肘より左手の位置が高い時、時計回りに玉が回転する。逆に左腕の肘より左手の位置が低い時、逆時計回りに玉が回転する。

描写モード 2 では、両手を左右に動かすと玉の生成位置が移動する。X 軸(横方向)しか取得していないため上下は反応しない。

動画が残っていたため以下に添付する。
(描写モード 1 の動画はどこかに無くした…)


補足説明として、
待機モードから描写モードに移るときに来場者人数をカウントする。その際、カウントした値は Unity 内で保管されるわけではなく、localhost の PHP サーバー上に保管される。相方が実装したのでよく分からないが、インターネット環境下で外部に PHP サーバーを置けば、外部から今来場者が何人来たか確認できるらしい。サーバー上に保管することによって、一旦アプリケーションを閉じて、再度実行しても来場者数はリセットされずにカウントを続けることができる。

描写モード 1 では、ほとんどスクリプトを書いていないので、描写モード 2 について書こうと思うが、長くなりそうなので物体生成のスクリプトだけ説明する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FlowerCircle : MonoBehaviour
{
// このコルーチンの処理を待たせる時間
public float WaitTime = 0.5f;

public float AllWaitTime = 1.0f;

public float WaitobjectTime = 0.05f;
// 周りに生成するオブジェクト
public GameObject[] objects;
// 周りに生成するオブジェクト (その子供)
public GameObject[] childobjects;
// 関節の番号 (自分で振る)
public int JointNumber = 0;

// オブジェクトを削除する時間
public float ObjDeleteTime;
// 子供のオブジェクトを削除する時間
public float childObjDeleteTime;
// 周りに生成するオブジェクト数
public int circleObjMax = 12;
// 座標の中心の object
public GameObject BaseObj;
// copy する object
private GameObject CloneObj;
private Rigidbody[] rb;


// Use this for initialization
void Start()
{

objects = new GameObject[50];
rb = new Rigidbody[50];
childobjects = new GameObject[50];
// オブジェクトを削除する時間
ObjDeleteTime = WaitTime * 11f;
childObjDeleteTime = WaitTime * 10.05f;

// circle 生成処理
StartCoroutine("OnCreateCircle");
}

IEnumerator OnCreateCircle()
{
//円の大きさ
int CircleDouble = 2;

while (true)
{
if (DataCenter.IsDetected[JointNumber] && DataCenter.GameMode == 1)
{
// プレイヤーの座標取得 (更新)
Vector3 basePos = BaseObj.gameObject.transform.position;
// 周りのオブジェクトを生成
for (int circleObjIdx = 0; circleObjIdx < circleObjMax; circleObjIdx++)
{
CloneObj = (GameObject)Resources.Load("MovingCreate");

// 正規化されたベクトル
Vector3 objVec = new Vector3(
CircleX(circleObjIdx, circleObjMax, CircleDouble),
CircleY(circleObjIdx, circleObjMax, CircleDouble),
0
);

// 周りの円の位置を計算(1回目)
Vector3 objPos = basePos + objVec;
// オブジェクトを生成
objects[circleObjIdx] = Instantiate(CloneObj, objPos, Quaternion.identity);

//rigidbody取得
Rigidbody rb = objects[circleObjIdx].GetComponent<Rigidbody>();
//オブジェクトに放射状に力を加える
rb.AddForce(objVec * 100);

// 作ったオブジェクトを一定時間後に消す
Destroy(objects[circleObjIdx], ObjDeleteTime);

// fade outを行う
StartCoroutine("FadeOut", objects[circleObjIdx]);

}

yield return new WaitForSeconds(WaitobjectTime);

// 一回目に生成した円中心に再度描写
for (int circleObjIdx = 0; circleObjIdx < circleObjMax; circleObjIdx++)
{
for (int circleChildObjIdx = 0; circleChildObjIdx < circleObjMax; circleChildObjIdx++)
{
// 正規化されたベクトル
Vector3 objChildVec = new Vector3(
CirclechildX(circleChildObjIdx, circleObjMax, CircleDouble),
CirclechildY(circleChildObjIdx, circleObjMax, CircleDouble),
0
);

// 周りの円の位置を計算
Vector3 objChildPos = objects[circleObjIdx].gameObject.transform.position + objChildVec;

// オブジェクトを生成
childobjects[circleChildObjIdx] = Instantiate(CloneObj, objChildPos, Quaternion.identity);
//rigidbody取得
Rigidbody rbc = childobjects[circleChildObjIdx].GetComponent<Rigidbody>();

//オブジェクトに放射状に力を加える
rbc.AddForce(objChildVec * 100);

Destroy(childobjects[circleChildObjIdx], childObjDeleteTime);
// fade outを行う
StartCoroutine("FadeOut", childobjects[circleChildObjIdx]);

yield return new WaitForSeconds(WaitobjectTime / circleObjMax);
}
}
}

yield return new WaitForSeconds(AllWaitTime); // n 秒処理を待つ
}
}

IEnumerator FadeOut(GameObject obj)
{
Vector3 objVecSub = new Vector3(0.2f, 0.2f, 0);

for (int i = 0; i < 5; i++)
{
obj.transform.localScale = obj.transform.localScale - objVecSub;

yield return new WaitForSeconds(1);
}
}

//一回目に円状に生成される玉のX座標
float CircleX(int circleObjNum, int circleObjMax, int Double)
{
float angle = circleObjNum * 360 / circleObjMax;
float x = Mathf.Sin(angle * (Mathf.PI / 180));
return x * Double;
}

 //一回目に円状に生成される玉のY座標
float CircleY(int circleObjNum, int circleObjMax, int Double)
{
float angle = circleObjNum * 360 / circleObjMax;
float y = Mathf.Cos(angle * (Mathf.PI / 180));
return y * Double;
}

 //一回目に生成された円を中心にして再度円状に生成される玉のX座標
float CirclechildX(int circleObjNum, int circleObjMax, int Double)
{
float angle = circleObjNum * 360 / circleObjMax + 360 / circleObjMax / 2;
float x = Mathf.Sin(angle * (Mathf.PI / 180));
return x * Double;
}

 //一回目に生成された円を中心にして再度円状に生成される玉のY座標
float CirclechildY(int circleObjNum, int circleObjMax, int Double)
{
float angle = circleObjNum * 360 / circleObjMax + 360 / circleObjMax / 2;
float y = Mathf.Cos(angle * (Mathf.PI / 180));
return y * Double;
}
}

玉が一斉に表示されてグチャグチャにならないように、コルーチンを使って玉が生成される時間に差をつけることでアニメーションを作った。(コルーチンの変数名が適当なのは申し訳ない…)


プレイヤーの座標取得
プレイヤーの取得座標を中心に円状に玉を配置して放射状に力を加える
WaitobjectTime秒待つ
最初に生成された玉1つを中心に玉を円状に玉を配置して放射状に力を加える。
(玉1つ生成毎にWaitobjectTime / circleObjMax秒待つ)
再度、最初に生成された玉1つを中心に玉を円状に玉を配置して放射状に力を加える。
(玉1つ生成毎にWaitobjectTime / circleObjMax秒待つ)
(最初に生成された玉の数(circleObjMax)回繰り返す。)
AllWaitTime秒待つ
最初に戻る



文章だとわかりにくいので図で簡潔に説明してみる。

circleObjMax=3 のとき

最初、プレイヤーの取得座標を原点と仮定すると下図のようになる。

次に最初に生成された玉を中心に再度下図のように描写。

みたいな感じ…

circleObjMax(玉の数)を変えても均等に配置される。

今回初めて github を使って共同制作した。複数人で 1 つの作品を制作-公開するにはすごく便利なツールだなと思った。(小並感)

他の説明は相方に任せます。良かったら見てください。詳しい説明乗ってます。

Unity と Kinect で作るジェネレーティブアート:Part2

スクリプトは相方の github 上で公開してます。

github:H37kouya/kinect-unity

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×