LightEffects
- 0 JPY
LEDCUBEというマイナーな開発物を学祭で作ったのですが、そのときに使用したアニメーションを作る自作ツールがよくできていたので, ほんのわずかなLEDCUBEをこれから開発してみようと思う有志の方々のためにソフトを配信します。LEDCUBEはダイナミック点灯を想定しています。 [スペック] ・windowサイズは全画面 ・LEDCUBE 5×5×5のみ対応可(需要次第では対応サイズ広げることもやらなくはないです) ・5fps~30fpsまで設定可能 ・フレーム数は1800Fまで設定可能
操作説明
右側のマス目をクリックすることでLEDの点滅箇所を選べます。 左下のタイムラインで編集するフレームを選択できます。 LEDCUBEのビューはスライドすることで回転が可能です。 ・キーボードのAとDで左右にタイムラインを移動させられます。 ・Frame Rate・・・fpsのオプション ・Play Time・・・フレーム数のオプション ・Frame Copy・・・現在のフレームのLED点灯パターンをコピー ・Frame Paste・・・現在のフレームのLED点灯パターンをペースト ・Reset Rotation・・・回転状態をデフォルトにする ・Reset FrameBuffer・・・現在のフレームのLED点灯パターンをリセットする ・Save&Load・・・現在のアニメーションデータをjson形式で保存&ロードできます ・Serialize to Processing・・・Processingに適したアニメーションデータを作成します。 ・Seeialize to Arduino・・・Arduinoに適したアニメーションデータを作成します。
動作環境
Windows 11/10/8/7 軽量なソフトなので、コンピューターのスペックはよほど古いものでない限り動くと思います。
データの読み取り方法
Processingへのリアルタイムレンダリングの出力方法とArduinoのコードに直書きできる出力方法の2通り実装してます。 (Aruduinoに直書きする場合) ほとんどの人はこちらを使うことになると思います。 出力フォーマットは以下のように出力されます。 //////////////////////////////////////////////// uint32_t pattern_2d[][5] = { {0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}, {0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}, {0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}, {0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}, ............. }; //////////////////////////////////////////////// pattern_2dという変数に1フレーム毎に5レイヤーごとのバイナリーデータが16進数表記で2次元配列として格納されます。 次にこのバイナリーデータと各LEDの対応付けについて説明します。 まずはじめに、この5つのレイヤーはy軸(上から下)を意識した設計となっています。なので、pattern_2dの[0][0]には0フレーム目の上から1番目のレイヤーの情報が入っています。 そのバイナリーデータは 例えば以下のようなデータが1レイヤーに存在したとします 0xA782BF80 この場合、2進数に直すと 1001 0111 1000 0010 1010 1111 1000 0000 となります。 このうち、下7桁は捨てデータとなります。 なので、アニメーションパターンは残りの25桁になり、"1"が点灯、"0"が消灯を表しています。 ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ これはLEDCUBEの1レイヤーを上から見た図です。 この図と見比べつつ、解釈していってください。 まず、下8桁目は左上のLEDの点灯の有無を指します。 次に、下9桁目~12桁目(16進数でいう"F"、2進数でいう"1111")は一番左の列の上から2行目~5行目を指します。 この調子で、下桁から一列のデータを当てはめたら、次の列に、そしてまた次の列に...を繰り返してデータがLEDと対応するような設計を意識してます。 これらの順序通りにご自身のLEDCUBEがうまく対応するようにArduino側でプログラムを組めばうまく表示されるはずです。 (Processingの場合) こちらは、主に自分向けの機能となります。ProcessingでLEDCUBEにリアルタイムレンダリングをどうしてもさせたかったので、アルゴリズムでアニメーションを作ったついでにデータ型のアニメーションも一緒に流したいってことで作りました。 これはLEDの点灯パターンが0と1のビットパターンとして書き込まれます。 そのデータはsplit関数によって要素を抽出することで各LEDごとの点灯の有無を読み込めます。 これだけではわからないと思うので、コード具体例を載せときます 1.Processingのpdeソースファイルと同ディレクトリー上に"data"というフォルダを作成し、そこにソフトで生成されたアニメーションデータを置きます。 2. //このクラスを作成し、インスタンス化することでデータが読み込まれます。ファイル名には任意の名前を入力してください。 //////////////////////////////////////////////// class AnimationData{ String[] dataLines; //ファイルテキスト格納変数 String dataLine; //段数ごとの配列データを一つの文にまとめる変数 String[] data; //LED単位で点灯の有無を格納する変数、LEDCUBEのLED数×フレーム数のデータが格納されます public ArrayList<AnimationBuffer> result; //最終的な加工されたデータを格納する変数、設計上ArrayListによって、フレームごとの配列を管理します。(AnimationBufferクラスは後述します。) AnimationData(){ dataLines = loadStrings("data/MySeltFile.txt"); //このメソッドを呼ぶことで、うまくディレクトリーのファイルが読み込まれれば、データが変数に文字列データとして格納されます。ちなみに配列には、段数ごとのデータが入ります。 dataLine = whileLoop(hanabiLines); //whileLoop関数によって、複数の段数を一つにまとめます。 result = new ArrayList<AnimationBuffer>(); load(dataLine,data,result); } String whileLoop(String[] lines) { int lineIndex = 0; // 現在の行のインデックス String line = ""; while (lineIndex < lines.length) { line += lines[lineIndex]; lineIndex++; // 次の行に移動 } return line; } private void load(String line,String[] data,ArrayList<AnimationBuffer> animationData){ data = line.split(","); for(int i = 0;i < data.length;i++){ int x = i%5; int y = i/25%5; int z = i/5%5; if(i%125==0) animationData.add(new AnimationBuffer()); animationData.get(i/125).buffer[x][y][z] = int(data[i]); } } } //////////////////////////////////////////////// 一緒にフレームデータを格納するクラスも一緒に作成してください。(先程出てきたAnimationBufferです) //////////////////////////////////////////////// class AnimationBuffer{ public int[][][] buffer; AnimationBuffer(){ buffer = new int[GRID_ROW_MAX_NUM][GRID_COL_MAX_NUM][GRID_DEPTH_MAX_NUM]; initBuffer(); } void initBuffer(){ for(int i = 0; i < GRID_ROW_MAX_NUM; i++){ for(int j = 0; j < GRID_COL_MAX_NUM; j++){ for(int k = 0; k < GRID_DEPTH_MAX_NUM; k++){ buffer[i][j][k] = 0; } } } } public void setBuffer(int[][][] b){ for(int i = 0; i < GRID_ROW_MAX_NUM; i++){ for(int j = 0; j < GRID_COL_MAX_NUM; j++){ for(int k = 0; k < GRID_DEPTH_MAX_NUM; k++){ int data = buffer[i][j][k]; b[i][j][k] = data; } } } } } //////////////////////////////////////////////// 以上でフレームごとのバッファとしてファイルのデータが読み込まれ、Processing上でデータとして扱えます。データの扱い方はArduinoの場合で記述したものと一緒です。