2012/11/17

公式には32bitドライバしかないアナログキャプチャを64bitのOSで動かす

ターゲットはこれ。S端子とコンポジット入力に対応したアナログキャプチャBOX で、USB2.0 接続のハードウェアエンコードタイプのデバイス。対応形式はMPEG1またはMPEG2。(チップの型番はこちら)中古価格は1000~3000円ぐらい。

三行で概要

32bitドライバしか配布されていないデバイスがある。(そしてちょっとしたinfの変更でも対応できなかった

そこで基盤が同じだけど別メーカーのデバイスの 64bit 用ドライバがある場合、それでインストールしてしまう。

あとは Windows 7 上でも VLCメディアプレーヤーを使えば、プレビューしながら録画できるようになる。

くわしい手順

の前に

実行は自己責任でお願いします

ちなみに、ここに書いてある以外にさらに改造しようと inf を書き換えたりしていると、PC-MDVD の 電源LEDが赤と黄色の点滅を繰り返すようになり二進も三進もいかなくなることがあります。そういうときはドライバを削除したり、ポートを変えるといいです。

なおBUFFALO の付属ソフト PCast も使えなくなるので注意してください(VLCメディアプレーヤーなどで録画します)

(1) 一度ドライバインストールしている場合はアンインストールしておく

もし PC-MDVD/U2 のドライバをインストールしている場合は、念のため、アンインストールしておく。

「コントロールパネル」から「デバイスマネージャ」を開いて「サウンド、ビデオ、およびゲームコントローラ」からPC-MDVDを探し、右クリックして「削除」しておく。

その後、デバイスマネージャのメニューの「操作」→「ハードウェア変更のスキャン」をすれば、「ほかのデバイス」に「不明なデバイス」などの名前で再び表示される。(USB の抜き差しで再認識させてもいい)

(2) ドライバをダウンロード

Grabster AV 400 MX の 64bit 用ドライバーを入手する。

ドライバー配布ページ から、「Windows 7 (64bit)」など使用しているOSのドライバーを選択し、名前をつけて保存する。

ありがとう Terratec

(3) ドライバのインストール

ダウンロードしたドライバのインストーラー(grabster_av_400_mx_drv_setup_xxxxxxxx_vista_7_8_64bit.exe)を実行します。

まずインストールする言語を聞かれるので、「Englisch(English)」を選びます。

何も考えたくなければ OK と Next と Finish をおしてればいいです。

以下の画面がでた場合は、もちろんインストールをクリックします。

以下の画面がでた場合は、「インストールを完璧に終えるにはデバイスを再接続してもらわないといけないんだけど、それはあとでやります?インストーラーは終了してもいいッスか?」ってことなので、「はい」を押しておく。

(4) このデバイスのドライバはこれだと教え込む

いつでもいいけど、このへんで USB で接続しておく。自動的に行われるドライバのインストールは失敗に終わると思うけど気にしない。

それで、デバイスマネージャの「ほかのデバイス」に表示されているデバイスのうち、PC-MDVD と思われるもの(「不明なデバイス」かもしれない)を右クリックし、「ドライバーの更新」を選ぶ。

以下の画面になったら、「コンピューターを参照してドライバー ソフトウェアを検索します」を選択する。

次は「コンピューター上のデバイス ドライバーの一覧から選択します」を選択する。

次は「すべてのデバイスを表示」を選択し「次へ」をクリックする。

しばらく検索が行われたあと、以下のような画面になるので左欄から Terratec を選択し、Grabster AV 400 を選択し、「次へ」をクリックする。

以下のような警告画面がでるので、よければ「はい」を選択する。

インストールが成功すれば、以下のような画面が表示される。

デバイスマネージャにも表示された。

(4) 再生してみる

VLCメディアプレイヤー をダウンロードして適当にインストールする。

メニューの「メディア」から「キャプチャーデバイスを開く」をクリックする。

以下のような設定画面が現れるので、デバイス選択のビデオデバイス名の一覧から「Grabster AV 400 Analog Capture」を選択して、画面下の再生ボタンを押す

問題なければ再生できるはず。(白い画面が表示される場合は失敗していて、たぶん環境が違うせいかな。がんばれ…)

(5) 録画してみる

(5-1) まずは保存先を設定する

メニューの「ツール」→「設定」をクリックし、右欄から「入力とコーデック」を選択(表示設定がシンプルの場合)。

「レコードファイル名、またはディレクトリ」に、好きな保存先を入力する。画面下の「保存」で保存して設定画面を閉じる。

(5-2) 次に録画ボタンを表示する

メニューの「表示」→「拡張制御」をクリックして、チェックをいれる。

あとは画面下に表示された赤丸のボタンをクリックすれば、指定した保存先にファイルが作成されていく。

録画の終了にはもういちど赤丸の録画ボタンを押す。

(いうまでもないけど録画中はファイルに書き込み中なので編集したければコピーするか、録画終了しとく)

(6) やったね!の後

ちなみに、(4) のキャプチャデバイスの設定で、デバイス選択のとなりにある「設定」ボタンを押すと、設定画面がでてくる。動画のビットレートやノイズ除去、色調調整の設定などが行える。

他のデバイスに応用する場合

BUFFALO や IO-DATA のようなメーカーサイトでは元ネタの基盤の名前までは載せていない。のでまずネットで検索して、なければ壊さないように開けて確認して、再び検索するといと思う。

追記: コメント欄より BUFFALO PC-SMP2E/U2 の64bitドライバーの配布URLを教えていただきました。匿名さん、ありがとうございます。

他にも動きそうですぜ

以下は中身の基盤が同じみたいなので、付属ソフト等の違いだけと思われる。

実際、ドライバも *.inf ファイルは機器の名前を変えたりしているくらいだったし、メインの p2usbwdm.sys ファイルもハッシュが同じだった。(IO-DATA のは落とせなかったが多分同じだろう)

BUFFALO の PC-MDVD は、基盤の型番が BMP837 なので、本当の元ネタは Yuan 製の BMP837 かな。

Linux 用のドライバもあるそうだ

pvrusb2 という Linux 用ドライバもあるようです。まだ使ってませんが録画鯖を安く作れるかも。

コンポジット入力とS端子入力の切り替え

入力端子の切り替えは VLCメディアプレイヤー ではできないようだ。

そこで ふぬああ を使う(他にも アマレコTV でも設定できた)。

ふぬああでは表示はできないが、設定画面にアクセスでき、ここで設定すれば他のソフトでも設定が有効になる。

ツールバーからデバイスの設定を開いたら、ビデオデバイスを「Grabster AV 400 Analog Capture」にして、第一クロスバーをクリックする。

表示された以下の画面で、Video SVideo In を選択する。

搭載されているチップ

  • CONEXANT / CX23416-22
  • CONEXANT / CX25837-44

基盤の画像

高画質な基盤の画像。チップを見たい人向け

音をオーディオインターフェースでとる場合

音ズレがおこる。遅延するsecを設定すればいいのかもしれない。

このやり方だとダメだった

これを実行する前に、inf ファイルに NTamd64 や NTia64 を追加して云々という方法も試したが、ある程度はインストールを進められるものの、「ドライバーはこのプラットフォーム用ではありません」とでてしまい、ドライバインストールに失敗した。

2012/10/26

amazon.co.jpでkindle版のリクエストを簡単にするchromeの拡張機能を作った


Kindleストアがはじまったamazon.co.jpで、kindle版がない書籍のリクエストを簡単にできるようにするchromeの拡張機能作った。

今までだと、カテゴリで絞り込んだ一覧や検索結果が表示された状態で、各リンクをクリック→リクエストをクリック→戻る、っていう作業が必要だった。KindleDeKure をインストールすると、一回のクリックで送信できるようになる。

インストール方法

Chrome ウェブストアの「KindleDeKure」のページをChromeで開き、インストールしてください。

アンインストール方法

〓みたいなボタンを押して、「拡張機能」を開いてアプリを削除してください。

その他

使用は自己責任で行ってください。

2012/09/24

Parthenonで起こるエラーの解決法

Parthenon(パルテノン)というレンダラを試しているときに見つけた、ファイルを読み込めない症状と、その対処法をまとめてみます。(はまりやすい仕様も含む)

前提知識

読み込める形式はMetasequoiaの.mqoファイル。.mqoファイルではテクスチャは外部の画像ファイルで指定する。Parthenonの読み込める画像の形式はREADMEによると「.bmpと.jpgのみ確認済み」。

その他ParthenonのREADMEは必読でした。

ケース別

エラーのダイアログが表示された場合、ソフトを再起動しないと読み込みできるファイルも開けなくなるので注意。

読み込めるが、表示されなかったりする場合

うまく表示されない、レンダリングが固まる、フリーズする、画面が真っ白になる

  • .mqoファイルを保存するとき、「名前を付けて保存」→「バージョン2.2互換」で保存する
  • すべて四角面を三角面化する
  • 曲面やミラーをフリーズする

エラーが表示され、読み込めない場合

「読み込み違反がおきました」と表示される場合

以下のようなエラー。

  • モジュール 'Parthenon.exe' のアドレス 0048853D でアドレス 0000004C に対する読み込み違反がおきました。
  • 0による浮動小数点数除算

材質(マテリアル)が何も定義されていないと起こった。材質を一つ以上作成すると解決。材質の作成だけでよく、このとき面に材質を設定する必要はない。

「ファイル C:\\hogehoge.jpg は開けません.」と表示される場合(テクスチャが開けない)

テクスチャの画像ファイルhogehoge.jpg(この例の場合)が見つからないときに表示される。

メタセコイアでテクスチャを指定するときに「hogehoge.jpg」としている場合、.mqoファイルからみて同じフォルダにないといけない。「フォルダ名\\hogehoge.jpg」としている場合、.mqoと同じフォルダにある「フォルダ名」というフォルダの中に、hogehoge.jpgがないといけない。「c:\\hogehoge.jpg」としている場合、Cドライブにhogehoge.jpgがないといけない。

「ストリームの読み込みエラー」と表示される場合

bmpを保存するソフトによってこれが起きたりした。

簡単な解決法は以下が考えられる。→(バイナリを修正する解決方法はこちら)

  • bmpを保存するソフトを変えて保存しなおしてみる
  • bmpをやめてjpgにしてしまう

その他

他にもあったら教えてください。さい!


おまけ

「ストリームの読み込みエラー」の根本的な原因

あるテクスチャがbmpの場合で、そのbmpが以下の条件を満たすときエラーが起こる。

  • 末尾に数バイトの0が追加されている(0以外の値の場合もあるかも)
  • ビットマップのヘッダ「BITMAPINFOHEADER」のDWORD値「biSizeImage」がその数バイトの0まで含めたサイズを格納している

たぶん、倍数にあわせて埋め草で0を追加するタイプのソフトでこういうファイルが作成され、parthenonが数バイトの0をデータとして読み込み、さらにファイルの末尾をこえてデータを読み込みに行こうとして、エラーが起こったのだと思われる。

なので、

  • 末尾の数バイトの0を削除する
  • biSizeImageの値を削除したバイト分を引いた値にする

とすれば解決する。

2012/08/28

Three.jsで3Dの画面をグリグリ回転させられるTrackballControlsについて

3Dのプログラムを公開するときにマウスで簡単に回転やズームができるとグリグリ動かせて楽しいです(公式のサンプル)。3DPlotColor.jsでも使ってます。

JavaScriptのライブラリThree.jsにはカメラをコントロールするTrackballControlsオブジェクトというのがあります。何行か書くとマウスやキーでのコントロールができるようになります。

ただプロパティまで解説したものがおそらくないので、チュートリアルと一緒に書いてみました。

前提知識としてはだいたい、Three.jsでサンプルを動かしてみてinit()関数やrender()関数がなにをするかを大雑把に把握している人を想定してます。

入門はヨモツネットさんのTHREE.jsでWebGL | ヨモツネットという記事などが詳しくていいと思います。

公式からソースをパクってきた

公式にあるとても短いソースをTrackballControls対応にしました。元々オブジェクトが回転するようになっていたので、そこを削って、背景色がグレーの行を変更/追加しました。

var camera, controls, scene, renderer;
var geometry, material, mesh;

init();
animate();

function init() {

    camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
    camera.position.z = 1000;

    controls = new THREE.TrackballControls( camera );

    scene = new THREE.Scene();

    geometry = new THREE.CubeGeometry( 200, 200, 200 );
    material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );

    mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );

    renderer = new THREE.CanvasRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );

    document.body.appendChild( renderer.domElement );

}

function animate() {

    requestAnimationFrame( animate );

    renderer.render( scene, camera );

    controls.update();

}

1行目で、あとで使うのでcontrolsを新たに宣言してます。

12行目で、TrackballControlsクラスをnewしています。渡すのはカメラです。

35行目のTrackballControlsのupdate()関数で、操作を反映しているようです。

この三行を追加すると、最低限動くようになります。その他は、12行目のあとにでも以下のプロパティで設定します。

TrackballControlsのプロパティ

プロパティの基本的なものは以下です。

controls.rotateSpeed = 1.0; //回転させるときの速さ
controls.zoomSpeed = 1.2; //ズームするときの速さ
controls.panSpeed = 0.3; //パンするときの速さ

controls.noRotate = false; //trueで回転操作を不可にする
controls.noZoom = false; //trueでズーム操作を不可にする
controls.noPan = false; //trueでパンの操作を不可にする

staticMovingプロパティは、iPhoneなどのように回転操作等をやめた瞬間にピタリと止まらないようにします。

staticMovingプロパティがtrueなら、マウスから手を離すとすぐ回転操作等を止めます。falseならdynamicDampingFactorプロパティで指定された係数で回転操作等を減衰させつつ行います。(0<dynamicDampingFactor≦1)

controls.staticMoving = false;
controls.dynamicDampingFactor = 0.3;

minDistanceとmaxDistanceプロパティはズームの設定です。以下の値は初期値です。最小の距離が0なのでどこまでも近づくことができ、最大の距離が無限なのでどこまでも遠ざかることができます。

controls.minDistance = 0; //近づける距離の最小値
controls.maxDistance = Infinity; //遠ざかれる距離の最大値

keysプロパティは、キーコードで指定したキー(この場合A・S・D)を押しながらマウスを動かす操作で、回転・ズーム・パンを行えるようにします。

controls.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];

そのほかのカメラコントロールについて

他のは解説が難しそうなんでリストだけ載せときます。とりあえず酔います…

FirstPersonControls(公式のサンプル)
マウスを左右に動かしたら左右を見て、クリックで進む、右クリックで戻る、みたいな人の視点ぽいカメラコントロール
OrbitControls(公式のサンプル)
FlyControls(公式のサンプル)
PathControls(公式のサンプル)

2012/08/26

色の分布を3Dで表示するJavaScriptをThree.jsで作った

画像の色の分布を3Dで表示するJavaScriptをThree.js(WebGL)を使って作った。

(WebGLが利用できるブラウザでないと動かないので、FireFoxやChromeでみてください)

サーバーに送信されることなく好きな画像の分布も表示できるので、遊べるんじゃないかと思います。

色空間について

使っている技術としては、まず3Dで表したときに人間の近くに近いらしいL*a*bという色の表し方へRGBをある程度決めうちしつつ変換してます。

ちょっと調べた限りでは、本当はRGBの情報だけではLabに変換できないと思いますが、本物との差は分布を出すだけなら無視していいと思ったのでそのままです。

それで、その変換した分布をJavaScriptのライブラリThree.jsのParticleの親玉のようなParticleSystemオブジェクトにパーティクルをいっぱい置いて表示してます。

WebGLなのでパーティクルが数万あっても軽い。

画面をマウスでグリグリ動かす

3Dをマウスでグリグリ回して見られるのは、Three.jsのTrackballControlsオブジェクトのおかげです。→詳しく記事を書きました。

そもそもの発端


そもそも絵を描くときに色が単純だと安っぽくなるけど、グラデーションをどうかけたらいいかがわからなかった。

そこで色の分布が出せたらわかるんじゃないか?と思って作った。

3DPlotColorで実際に表示させてみると、自分の絵は非常に単純な形で色が置かれていることがわかる。プロの人は色が複雑で写真に近い。

というわけで色を変化させるときはここに注意しながら、また絵を描いみようと思う。

参考にさせてもらったサイト様

色空間の変換(3)
RGBからLabへの変換はこちらのサイトの変換式を参考にしました。
Creating Particles with Three.js | Aerotwist(英語)
Three.jsでのパーティクルのチュートリアルがあります。
写真素材 足成【フリーフォト、無料写真素材サイト】
綺麗な画像のサンプルは一部ここからいただきました。著作権表示やリンクも必要ない画像の素材サイトです。(おおぶちゃんも教えてくれてありがとう)

追記

@yoyaさんにいろんなバージョンを作ってもらいました。(ブログ記事はこちら

RGB色空間バージョン
HSV色空間バージョン

追記2

色空間を選べるようにしました。dat.GUIというjsのライブラリを使ってあります。Three.jsのデモでも使われているライブラリで、画面の邪魔をしないので相性がいい気がします。基本的なGUIや、階層表示もあって、プリセット機能もつけられるっぽいです。→サンプル(dat.GUIの公式サイト)

軸もみやすくなりました。@yoyaさんの軸を虹色にするコードも取り入れさせてもらいました。


2012/07/31

gccのコンパイルエラーで、ライブラリファイルが読み込めないときの対処

gcc -o hoge.obj -c hoge.c
gcc -o hoge.exe hoge.obj -L"c:\msysgit\msysgit\mingw\lib\" -l"libws2_32.a"

winsock2を使ったプログラムを作った。そしてmingw+gccの環境で上記のようにコンパイル(&リンク)させようとしたところ、以下のような「ファイルが見つからない」というエラーがでた。

c:/msysgit/msysgit/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../../mingw32/bin/ld.exe: cannot find -llibws2_32.a
collect2: ld returned 1 exit status

ファイルの場所を確認してもlibws2_32.aファイルはたしかに存在するので、検索してみた。

海外のサイトによると、リンカー(ld.exe)はlibや.aのないファイル名が欲しいらしい。

というわけで、libと.aを取り払って以下のようにすると成功した。

gcc -o hoge.obj -c hoge.c
gcc -o hoge.exe hoge.obj -L"c:\msysgit\msysgit\mingw\lib" -l"ws2_32"

それを確かめたあと、コマンドラインのヘルプを見に行くと答えがわかった(順番が違ったね…)。

ファイル名を指定するのであれば、そのままファイル名を書けばよく、ライブラリかオブジェクトかはプログラムが判断するという。

-lオプションはlibと.aをつけて検索してくれる便利なオプションだった。

`-l'オプションを使うこととファイル名を指定することの唯一の違いは、 `-l'オプションの場合には、 libraryの前後に`lib'と`.a'とが付加されて、 いくつかのディレクトリが探索されるという点にあります。
gcc -o hoge.obj -c hoge.c
gcc -o hoge.exe hoge.obj "c:/msysgit/msysgit/mingw/lib/libws2_32.a"

一応メモしておく

2012/07/16

Bsurfacesの日本語訳ヘルプ

http://ikaflower.org/ja/bsurfaces/

BlenderのリトポロジーのプラグインBsurfacesのヘルプを日本語に訳した。

2012/07/03

ico形式用のStirling構造体定義ファイル

バイナリエディタStrilingの構造体定義ファイルを作成した。

Stirlingの構造体編集機能はバイナリのデータを見るときに便利な機能で、構造体をC++のソースのように定義しておけば、バイナリのデータを表で見ながら編集することができる。構造体を内包している構造体も定義できる。

ICOファイルのフォーマットの詳細は以下のページが詳しかった。

http://www14.ocn.ne.jp/~setsuki/ext/ico.htm

さて、画像データのヘッダはBitmapInfoHeaderでBMPと同じものなので、定義はIconFileHeaderとIconInfoHeaderを書くだけで済んだ。BitmapInfoHeaderは付属のstruct.defにある)

以下をstruct.defの末尾に追加してください。

struct.def

struct IconFileHeader
{
 WORD icoReserved;
 WORD icoResourceType;
 WORD icoResourceCount;
};

struct IconInfoHeader
{
 BYTE Width;
 BYTE Height;
 BYTE Reserved1;
 WORD Reserved2;
 WORD Reserved3;
 DWORD icoDIBSize;
 DWORD icoDIBOffset;
};

IconFileHeaderは、アイコン一枚のケースが多いのでだいたい00 00 01 00 01になる。

「stirling 構造体」で検索してこられる方が多いので追記

「構造体」を表示するということは、バイナリを何バイトかずつに分けて、見やすく表示するということです。

構造体自体は元々プログラミングの用語で、その名のとおり構造をもったデータのことです。

じゃ、Tomoedaという名前の構造体をつくり、そのなかにKinomotoという1バイトのデータを入れてみます。

struct Tomoeda
{
 BYTE Kinomoto;
};

換言すれば、

struct 構造体の名前
{
 データ;
};

ということです。末尾の;(セミコロン)は、データの定義などの終端を表します。

データのほうは、以下のように定義します。

データの大きさ データの名前;

Kinomotoはデータの大きさが1バイトなのでBYTEになります。2バイトならWORD、4バイトならDWORDとします。

LONG(4バイト)というものもありますが、よその定義では定義が違ったりと曖昧なので使わないようにしてます。

たまにデータの名前にこんな[数字]がついていることがあります。

BYTE Kinomoto[3];

たとえば木之本さん一家の年齢のデータが、2B 11 0Aという3バイトで入っているとします。Kinomoto1、Kinomoto2、Kinomoto3というデータ名で1バイトずつ分けることもできますが、そんな命名をしていたら時間がかかるので、[総数]とデータの名前のあとに書くことで、総数分のデータであるというふうにかけるわけです。

いわゆる配列ですね。お役に立てたら幸いです。

2012/06/29

Windowsでファジング用のファイルを一気に作成するプログラムとバッチスクリプト

Bugハンター日記」という、プログラムの脆弱性の発見方法について書いた本を買いました。

その中にiPhoneをハックする章があります。

そこでは、

  • 特定のフォーマットの正常なファイルを一つ用意
  • ファイルの中の1バイトだけが異なるファイルを何パターンも作成
  • それを自動でアプリに開かせる

このように網羅的なアタックでアクセス違反が起こるかどうかを見るという方法が使われていました。

こういうテスト手法はファジングと言うらしいです。

さて、このファジングのためにファイルを1バイトだけ書き換えるプログラムが、ソースは載っているのですが、Windowsでは動かない関数が使われていました。

なので Windows環境でコンパイルできるCプログラムを書きました。

gcc -o fuzz fuzz.c

もしgccがない場合はMinGWなどをインストールしてください。

fuzz.c

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
 int hdl;
 char *name = NULL;
 unsigned int file_offset = 0;
 unsigned int file_value = 0;

 if(argc<2){
  printf("Error: not enough arguments\n");
  return 1;
 }else{
  file_offset = atol(argv[1]);
  file_value = atol(argv[2]);
  name = argv[3];
 }

 hdl = open(name, O_RDWR | O_BINARY);
 if(hdl==-1){
  perror("open");
  exit(1);
 }

 if(lseek(hdl, file_offset, 0)==-1){
  perror("lseek");
  exit(1);
 }

 printf("file offset: 0x%08x (value: 0x%08x)\n", file_offset, file_value);

 if(write(hdl, &file_value, 1)==-1){
  perror("write");
  exit(1);
 }
 
 close(hdl);

 return 0;
}

ちなみにあまり引数の正しさをチェックしてません。オフセットに変な値を渡したりしないほうがいいです。

引数は以下のように渡します。

fuzz.exe funny.doc 10 255

この場合、funny.docの10バイト目を255にして上書き保存します。

また、これを使って次々にファイルを生成させるバッチファイルも作成しました。

go.bat "C:\music\test.ogg" 10 -1

のように使います。

この例では、test.oggを、10バイト目から終端まで(-1を指定すると終端までになります)、1バイトずつ変えては保存します。test10.ogg test11.ogg ... といったファイルが出力されます。

go.bat

@echo off
REM 書式: go.bat "元ファイルへのパス" オフセット 終了するオフセット
REM 例 : go.bat "c:\hoge.doc" 0 100

REM forの中で変数をカウントしながら使えるようにする
REM (遅延環境変数という。%x%のかわりに!x!のように使う)
setlocal ENABLEDELAYEDEXPANSION

REM 環境変数を汚さないように一時的なモードにする
setlocal

REM ファジングをはじめる位置。10進数
set /A off=%2
set /A max=%3
REM ファジングで上書きするときの値。0?255。10進数
set val=255

REM 元にするファイルが存在しない場合エラーを出して終了
if not exist "%~f1" (
 echo "loading...%~f1"
 echo "Error: source file is not found"
 goto destructor
)

REM 位置(オフセット)と終了位置が範囲内にあるか
if "%max%" EQU "-1" (set /A max=%~z1)
if %~z1 LSS %off% (goto invalidoffset)
if %off% LSS 0 (goto invalidoffset)
if %off% GTR %max% (goto invalidoffset)

for /l %%i in (%off%,1,%max%) do (
 cp "%~p1%~n1%~x1" "%~n1%%i%~x1"
 set /A off=off+1
 fuzz !off! %val% "%~n1%%i%~x1"
)

goto destructor

:invalidoffset
echo "Error: invalid offset(%off%) or max(%max%)"
echo "filesize: (%~z1)"
goto destructor

:destructor
REM 使い終わったので元に戻しておく
endlocal

2012/06/13

Three.jsとPhysijsで3D物理演算

three.jsという3Dのライブラリなどを使って、簡単に3Dの物理演算を行うための記事が本当に簡単だったので、翻訳させてもらいました。

著者のJerome Etienneさんはブログ「Learning Three.js」でさらにThree.jsやphysijs他色々な記事を公開されてます。記事で使用するThree.jsのエクステンションtQueryの開発者でもあります。

元の記事: 3D Physics With Three.js and Physijs


これは物理演算に関するさらに別の記事になる。この記事は、physijsというChandler Prall氏によるライブラリについての記事だ。このphysijsでは、ammo.jsthree.js を簡単に連携させることができる。以下で、それを使ったサンプルのコードを見てみることにする。3Dグラフィックスにおいて、物理演算はいつも重要なものだ。物理演算をすると、空間がよりリアルなものになる。ただ何かのオブジェクトをもってくるだけで、素敵に、リアルに動いてくれるだろう。なので一つ一つの動きを調整するなんてことに時間を費やす必要が少なくなる。とてもズボラな筆者には、ここは大事なところなんだ。ちなみに、screencast は、デモ(今回の記事で書くもの)のほか、ammo.jsを使って何ができるかがわかる様々なサンプルを公開しているよ。

物理演算エンジンについて

前回までに、three.js と物理演算についてみてきた。marblesoccerのミニゲームにmicrophysics.jsを使うというものだった。microphysics.jsは、3D物理演算を実装している非常に小さなライブラリだ。それについては、“Lets Make a 3D Game: microphysics.js”“Lets Make a 3D Game: microphysics.js, Even Easier”の記事でほんのちょっとふれたとおりである。microphysics.jsは、たった500行のライブラリなんだよ!ただ残念なことに、このきわめて少ない行数はいくつかの制限を生んでしまっている。

今日は、Chandler Prall氏のphysijsを使う予定だ。これは非常に素敵なライブラリで、three.jsとともにammo.jsを使うのを簡単なことにしてくれる。ammo.jsは、Bullet物理演算エンジンをEmscripten を使ってJavaScriptへ直接移植したもので、そのソースコードは自動でJavaScriptに変換されているため、機能的にはオリジナルのBulletとまったく同じものなのだ。

bulletは、3Dの世界ではよくしられた本格的な物理演算エンジンだ。ドキュメントをみるとわかるのだが、できることは多い。そしてammo.jsは、高機能な3D物理演算エンジンに期待される機能をすべて実装している。@ccliffe氏ことCharles J.Cliffe氏は、ammo.jsを使ったいくつかのデモをみせてくれている。一つは、heighfieldだ。あとstunt trackを見てほしい!なお、この二つは@ccliffe氏のライブラリであるcubicvrを使っている。

physijsはパフォーマンスを考慮して書かれている。ammo.jswebworkerの内部で実行されるので、だいたいの場合はマルチコアCPUを生かせるだろう。つまり二倍以上のCPU処理能力を作成するjavascriptにもたせることができるということなんだ。3Dの座標のデータは使用できるようになると、所有権の譲渡ができるオブジェクト(transferable objects)に交換される。「所有権の譲渡ができるオブジェクト」とは、メインスレッドとwebworkerの間で、データをコピーすることなくデータを移すことができるオブジェクトの特別な型のことだ。ということは、データがどんなに巨大であっても、待ち時間は非常に少なくなるだろう。

はじめよう

今日紹介するコードは、physijsに付属している衝突デモのサンプルをコピーしたものになる。あるプログラムを、同じ方法で実行できると確かにするために再び書き直してみるのは、役に立つこともある:) お試しあれ。というわけで、オブジェクトが地面に落ち、そこでわずかに反発するようにした。それじゃ、やってみよう。

まず典型的なところからさわろう。tQuery.Worldを作成すると、scene(空間)、レンダラ、カメラとカメラをコントロールするものといったオブジェクトがすぐに使えるようになる。これらには、適当な初期値が最初から設定されている。.boilerplate()とすると、“three.jsのひな型(boilerplate)”が追加される。これは去年記事にした。カメラコントロール(cameraControls)は使えないようにする。そして、レンダラの描画ループを動かすため.start()を実行する。

var world   = tQuery.createWorld().boilerplate({cameraControls: false}).start();

さて、sceneの中央から少し離れたところにカメラをセットする。そうすると、さらに大きなオブジェクトをおいてもちゃんと見られるようになった。

world.tCamera().position.set( 70, 40, 70 );
world.tCamera().lookAt( world.tScene().position );

さて、影付け処理が必要であるとレンダラに伝える必要がある。それは以下のシンプルな何行かのコードで実現できる。詳しくは“Casting Shadows”という記事で見たとおりだ。

world.tRenderer().shadowMapEnabled  = true;
world.tRenderer().shadowMapSoft     = true;
world.tRenderer().setClearColorHex( 0xffffff, 1 );

この空間に物理演算を適用することができるようになった。ここは重要なところだ。たった今から、この空間にある物理演算をするよう設定したオブジェクトは、リアルな物理法則にしたがって動くことになる。

world.enablePhysics();

ライトをつけよう

次はライトの設定をしよう。話を簡単にするために、一方向ライトのみを使用しよう。まず好みにあわせて配置位置と色を変える。感覚をつかむためにパラメーターを色々いじってみるといい。では、影についての設定を調整する。場合によっては難しいかもしれない。詳細は、"Casting Shadow"という記事で書いてあるので、それを見てもらってもいい。シャドウカメラ(訳注:カメラのように視野角などで設定できる影付けの方法がある)を可視化するときに便利だ。それには.shadowCameraVisible(true)を使う。

tQuery.createDirectionalLight().addTo(world)
    .position(20, 40, -15).color(0xffffff)
    .castShadow(true).shadowMap(512*2,512*2)
    .shadowCamera(60, -60, 60, -60, 20, 200)
    .shadowDarkness(0.7).shadowBias(.002)

地面を作ろう

まず地面にはるテクスチャを作ろう。岩の感じをだすためにrocks.jpgを使おう。面の上でテクスチャを繰り返すには.RepeatWrappingを使う。それから、適切な大きさにしよう。

var texture = THREE.ImageUtils.loadTexture( "images/rocks.jpg" );
texture.wrapS   = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 3, 3 );

まあ実際には、地面は広くて平坦な立方体だ。昔の人が信じていた地球平面説とちょっと似ている:) それはいまや普通のことだね。さてここまでで、配置位置、材質、影について設定できた。

var ground  = tQuery.createCube(100, 1, 100).addTo(world)
    .position(0, -10, 0)
    .setLambertMaterial().map(texture).back()
    .receiveShadow(true)

さて、地面の物理演算について設定をしないといけない。これは.enablePhysics()で設定できる。引数massで、この物理空間でのこのオブジェクトの重さを定義している。ちなみにデフォルトでは、オブジェクトの大きさから自動的に計算される。ここでmassを0にしているのは、特別な意味があり、「常に重さは無限大であり、動くこともない(静的オブジェクトである)」ことを意味している。

ground.enablePhysics({
    mass    : 0
});

3D空間でオブジェクトを生成する

この空間でオブジェクトを生成するのはいつも、デリケートな問題だ。しかしまず、生成するオブジェクトのテクスチャを読み込んでしまおう。これはオブジェクトを生成するループの外で読み込むので、データが一度だけメモリに読み込まれ、残りは再利用される。よく知られているように、すべてのオブジェクトに対し、データは一度だけGPUへ送られる。パフォーマンス性を考えると、ここは重要なポイントだ。去年、"Performance: Caching Material"という記事でこれに関する話題をちょうどやった。

var cTexture    = THREE.ImageUtils.loadTexture( "images/plywood.jpg" );

さて、オブジェクトを生成する関数としてspawnObject()を宣言した。立方体を作り、配置や回転している角度・材質を設定した。いい感じだよ。あっ、シャドウマッピングが使えるように.castShadow()を使うのを忘れないようにしよう。

var spawnObject = function(){
    var object  = tQuery.createCube(4,4,4).addTo(world)
        .rotation(Math.random()*Math.PI*2, Math.random()*Math.PI*2, Math.random()*Math.PI*2)
        .position(Math.random()*15-7.5, 25, Math.random()*15-7.5)
        .setLambertMaterial().map(cTexture).back()
        .castShadow(true)

オブジェクトに対し物理演算を適用してみる。たった今から、この空間はすべての動きをコントロールできるようになる。独自に設定したパラメーターを使うと、それは物理の法則に反するだろう。以下のfriction(摩擦)は、二つのオブジェクトがお互いにこすれあうときにおこる反発の力だ。次のrestitution(反発)は、オブジェクトがどう跳ね返るかのパラメーター。学術的な定義は、本で見てね:)

object.enablePhysics({
        friction    : 0.4,
        restitution : 0.6
    });

さて、次は「衝突」のイベントをいじってみようと思う。Physijsはあるオブジェクトが別のオブジェクトに衝突したときに教えてくれる。それにはただ.addEventListener()を「衝突」のときに使えばいい。ここでは、何かに衝突した回数によってオブジェクトの色を変えてみることにする。

var nCollisions = 0;
    object.physics().addEventListener('collision', function(){
        var colliColors = [0xcc8855, 0xbb9955, 0xaaaa55, 0x99bb55, 0x88cc55, 0x77dd55];
        if( ++nCollisions < colliColors.length ){
            var color   = colliColors[nCollisions];
            object.get(0).material.color.setHex( color );
        }
    })
}

さて、一秒毎にオブジェクトを生成するのには、シンプルにsetInterval()を使うことにしよう。

setInterval(spawnObject, 1000);

これで終わり!リアルな3D物理演算をすることができた!やあ、悪くないね:)

まとめ

そんなわけで、今はphysijsがあるので、three.jstQueryを使えば、本格的でリアルな物理演算をすることができる。それは空間をよりリアルにするのには単純な方法だ。使ってみるのもいいだろう。また何かこの話題について書くと思う。

どうもありがとう。それじゃお楽しみください。:)


誤訳かな?と思われたら@ikaflower3ikaflowerあっとcrna.sakura.ne.jpまで教えていただけると大変嬉しいです。

three.jsのサンプルを求めてこられる方が多いので追記

three.jsのサンプルはこちらもオススメです。

http://yomotsu.github.com/threejs-examples/

2012/06/01

Three.jsで水滴シミュレータを作った話

この間、Three.jsをつかって簡単なプログラムを作った。(→RainDrops
盤面の水滴が動く3Dの画面が見られる。マウスで回転させて表示することもできる。

簡単に3D表示ができるThree.jsの話

Three.jsというライブラリのおかげで、あまり3Dの用語を勉強しなくても3D表示をすることができた。

なかでも、右クリックで表示しているものを回転させる部分は、とても便利な TrackballControls というのがあって、
controls = new THREE.TrackballControls(camera, renderer.domElement);
//renderer.domElementでは、回転などのマウス操作を有効にする範囲をDOMエレメントで指定している

controls.rotateSpeed = 5.0; //回転するときのスピード
controls.zoomSpeed = 5; //ズームするときのスピード
controls.panSpeed = 2; //パンするときのスピード
controls.noZoom = false; //ズームしない設定をOFF
controls.noPan = false; //パンしない設定をOFF

最低限、この最初の一行をinit()関数なりにいれておけば、3Dをグリグリ回しながら見られるようになるみたいだ。
簡単すぎてびっくりした。

少なくともちょっとした3Dのデータを見せることにも使えるし、夢がひろがる。

アルゴリズムの話

水滴シミュレータのアルゴリズムの方は、boids(ボイド)なんかを見て作った。

boidsは3つのルールで鳥の群れの飛行をシミュレートするもので、Three.jsにもサンプルがあったりする。

このRainDropsは、窓につく水滴が落ちていく様子を同様に3つのルール(boidsとはまた違うルール)でシミュレートする。

まず、水滴が落ちる「ガラス面」を二次元の碁盤のような平面に見立てる。水滴は一滴で一マスとして、水滴をその大きさで表すことにして「重み(weight)」と名づける。そして以下のルールで動かしていく。

  1. 雨が降る ランダムでマスに重みをつける。
  2. まとまる 隣接マスに水滴があるとき、マスすべての重みを足し合わせ、一つのマスにまとまる。
  3. 落ちる 一マスが一定の重さ以上のとき、一マス下へ移動する。

本当に単純なモデル化でシミュレートできるのかな、という疑問を解決するために書いた。

単純なルールで生き物のように動くことで有名なライフゲームも、最初はかなり複雑なルールでつくられていたらしい。

意外とお手軽にシミュレーションできるんだなと思った。

2012/05/19

SDカードの画像を特定フォルダへ自動転送するバッチスクリプト


デジカメのSDカードから、特定のフォルダに移すことがあります。この作業を自動化するため、バッチスクリプトを書きました。

REM 保存先フォルダの指定
set outputdir=C:\photo

REM %date以降の文字列では2000-01-01(年-月-日)という形式の文字をつくる
set outputdir=%outputdir%\%date:~-10,4%-%date:~-5,2%-%date:~-2,2%
mkdir %outputdir%

REM この三重ループで、IからLまでのドライブにある、
REM 「DCIM\101MSDCF」フォルダまたは「DCIM\100MSDCF」にある、
REM 拡張子がjpg、jpeg、cr2のファイルをoutputdirに移動する
for %%i in ("I" "J" "K" "L") do (
    for %%j in ("DCIM\101MSDCF" "DCIM\100MSDCF") do (
        for %%k in (jpg jpeg cr2) do (
            if exist %%i:\\%%j\*.%%k (
                move /-Y %%i:\\%%j\*.%%k %outputdir%
            )
        )
    )
)

REM 使い終わったので消しておく
set searchdir=
set outputdir=


これをmovephoto.batなどで保存して実行します。

もちろんですが、forの中は適宜書き換える必要があります。

これで、outputdirで指定したフォルダの直下に2012-05-19のような名前のフォルダが作成され、該当ファイルが転送されます。

応用1:ファイルを移動ではなくコピーがいい場合は、moveをcpにします。

cp /-Y %%i:\\%%j\*.%%k %outputdir%
応用2:上書き確認をだしてほしい場合は、/-Yを消します。

move %%i:\\%%j\*.%%k %outputdir%

Eye-fiには手が出せないので、これでちょっとは楽になったかな…。