- 2024年10月
- 2021年5月
- 2020年8月
- 2020年6月
- 2020年5月
- 2019年1月
- 2018年8月
- 2018年6月
- 2018年5月
- 2018年3月
- 2018年1月
- 2017年12月
- 2017年11月
- 2017年10月
- 2017年9月
- 2017年8月
- 2017年7月
- 2017年6月
- 2016年11月
- 2013年9月
- 2013年8月
- 2013年6月
- 2013年5月
- 2013年4月
- 2013年3月
- 2013年2月
- 2013年1月
- 2012年12月
- 2012年11月
- 2012年10月
- 2012年9月
- 2012年6月
- 2012年5月
- 2012年4月
- 2012年2月
- 2011年7月
- 2011年5月
- 2011年4月
- 2011年2月
- 2010年12月
- 2010年11月
- 2010年10月
- 2010年9月
- 2010年8月
- 2010年7月
- 2010年6月
- 2010年5月
- 2010年4月
- 2010年3月
- 2010年2月
- 2010年1月
- 2009年12月
- 2008年2月
- 2008年1月
- 2007年12月
- 2007年5月
- 2007年4月
- 2007年3月
- 2007年2月
JavaScriptでバイナリデータの読み込み / magicien
JavaScriptでPMD、VMD等のバイナリデータを読み込んだときに使った方法。HTML5のAPIの実装が進めば、こんなことする必要も無くなる気がしますが、今使っている方法は次のとおり。
まずはファイルをバイナリとして取得する必要がある。
読み込みの対象がFileオブジェクトの場合は、FileReaderを使えばOK。
function readData(data) {
...
}
function readBinaryFile(file) {
var reader = new FileReader();
reader.onloadend = function() {
readData(reader.result);
};
reader.readAsBinaryString(file);
}
読み込み対象がサーバ上のファイルであれば、"charset=x-user-defined" として読み込む。例によって prototype.js を使っているので、Ajax.Requestのサブクラスを作って次のようにした。
var BinaryRequest = Class.create(Ajax.Request,
initialize: function($super, url, options) {
$super(url, options);
},
request: function() {
this.transport.overrideMimeType('text/plain; charset=x-user-defined');
Ajax.Request.prototype.request.apply(this, argument);
},
});
function readBinaryFileFromURL(url) {
new BinaryRequest(url, {
method: 'GET',
onComplete: function(response) {
readData(response.responseText);
},
});
}
これで、データを読み込むところまでは出来たので、あとはデータの解析をするだけ。とはいえ、そっちの方が大変ですが。データの解析はまた今度。
この記事のURL: https://darkhorse2.0spec.jp/171/
2012/09/29(Sat) 01:06:13
MacでのWeb用音声変換 / magicien
ウェブ用にmp3とoggとwavを用意するときに毎回分からなくなるのでメモ。・wav→mp3
こういうときに限ってQuickTimeが使えないので、iTunesを使う。
「iTunes」→「環境設定…」→「一般」→「CDをセットしたときの動作」の横の「読み込み設定」→「読み込み方法」で「MP3エンコーダ」を選択
その後、読み込んだ曲を右クリック(Ctrl+クリック)で選択、「MP3バージョンを作成」で出来上がり。
・mp3→wav
上と同じ。「読み込み方法」で「WAVエンコーダ」を選択
その後、曲を右クリック(Ctrl+クリック)で選択、「WAVバージョンを作成」で出来上がり。
・wav→ogg
oggencコマンドを使う。
FinkとかMacPortsとかで vorbis-tools をインストールすると、使えるっぽい。
$ oggenc -o output.ogg input.wavこれでOggファイルの出来上がり。
・ogg→wav
oggdecコマンドを使う。
同じく vorbis-tools でインストールされる。
$ oggdec -o output.wav input.oggmp3とoggの変換は一度wavにしてから変換すれば良いんじゃないかと思う。
あと、音声素材サイトでogg形式のファイルが公開されていると、おっ!と思う。
こことかおすすめです。
タグ:
この記事のURL: https://darkhorse2.0spec.jp/170/
2012/09/28(Fri) 00:31:18
Operaで "instanceof Image" がエラーになる / magicien
Operaで次のようなコードを実行したところ、"Unhandled Error: Second argument to 'instanceof' does not implement" というエラーになった。
var img = new Image();
if(img instanceof Image) {
alert("img is an instance of Image!");
}
なぜかImageにはinstanceofが使えないらしい。Operaで上のような判定をしたい場合は、Imageの代わりにHTMLImageElementを使えばOK。
タグ:
この記事のURL: https://darkhorse2.0spec.jp/169/
2012/09/27(Thu) 01:54:00
JavaScriptでベクトル、行列計算の高速化 / magicien
JavaScriptでベクトルや行列の計算を高速化しようとしてやったこと。WebGLを始めた頃、まだライブラリもさほど世の中に無い状態だったので、ベクトルや行列計算のライブラリを自分で実装しました。
3Dのプログラミングというと、8割方ベクトルと行列の計算なんじゃないかと思うのですが、ということは、ベクトルや行列の計算を高速化することで、プログラム全体の高速化が望めるのではないかと考えました。
で、いろいろと実験した結果、割と効果があったのが、ループアンローリングという手法。
CPUのパイプラインが云々で分岐を無くすことで、コードの先読みを有効活用したりデータの依存関係をコンパイラに分かりやすくしたりとかなんとかでまぁあれなんですけど、JavaScriptみたいなスクリプト言語で効果があるのやら駄目もとでやってみたところ、思いのほか有効でした。
ループアンローリングをしない場合だと、4x4の行列計算は次のような書き方になるかと思います。
// 行列の定義
var matrix1 = [[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34], [41, 42, 43, 44]];
var matrix2 = [[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34], [41, 42, 43, 44]];
var matrix3 = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]];
// 行列のかけ算
for(var i=0; i<4; i++){
for(var j=0; j<4; j++){
for(var k=0; k<4; k++){
matrix3[i][j] += matrix1[i][k] * matrix2[k][j];
}
}
}
ループアンローリングはループを全部展開してしまって、ループ毎に発生する分岐とindexの変数を無くします。ついでに、配列も無くしてしまって変数を参照するときのオーバーヘッドを少なくしてやります。
すると、
// 行列の定義 var matrix1 = new Object(); matrix1.m11 = 11; matrix1.m12 = 12; matrix1.m13 = 13; matrix1.m14 = 14; matrix1.m21 = 21; matrix1.m22 = 22; matrix1.m23 = 23; matrix1.m24 = 24; matrix1.m31 = 31; matrix1.m32 = 32; matrix1.m33 = 33; matrix1.m34 = 34; matrix1.m41 = 41; matrix1.m42 = 42; matrix1.m43 = 43; matrix1.m44 = 44; var matrix2 = new Object(); matrix2.m11 = 11; matrix2.m12 = 12; matrix2.m13 = 13; matrix2.m14 = 14; matrix2.m21 = 21; matrix2.m22 = 22; matrix2.m23 = 23; matrix2.m24 = 24; matrix2.m31 = 31; matrix2.m32 = 32; matrix2.m33 = 33; matrix2.m34 = 34; matrix2.m41 = 41; matrix2.m42 = 42; matrix2.m43 = 43; matrix2.m44 = 44; var matrix3 = new Object(); matrix3.m11 = 0; matrix3.m12 = 0; matrix3.m13 = 0; matrix3.m14 = 0; matrix3.m21 = 0; matrix3.m22 = 0; matrix3.m23 = 0; matrix3.m24 = 0; matrix3.m31 = 0; matrix3.m32 = 0; matrix3.m33 = 0; matrix3.m34 = 0; matrix3.m41 = 0; matrix3.m42 = 0; matrix3.m43 = 0; matrix3.m44 = 0; // 行列のかけ算 matrix3.m11 = matrix1.m11 * matrix2.m11 + matrix1.m12 * matrix2.m21 + matrix1.m13 * matrix2.m31 + matrix1.m14 * matrix2.m41; matrix3.m12 = matrix1.m11 * matrix2.m12 + matrix1.m12 * matrix2.m22 + matrix1.m13 * matrix2.m32 + matrix1.m14 * matrix2.m42; matrix3.m13 = matrix1.m11 * matrix2.m13 + matrix1.m12 * matrix2.m23 + matrix1.m13 * matrix2.m33 + matrix1.m14 * matrix2.m43; matrix3.m14 = matrix1.m11 * matrix2.m14 + matrix1.m12 * matrix2.m24 + matrix1.m13 * matrix2.m34 + matrix1.m14 * matrix2.m44; matrix3.m21 = matrix1.m21 * matrix2.m11 + matrix1.m22 * matrix2.m21 + matrix1.m23 * matrix2.m31 + matrix1.m24 * matrix2.m41; matrix3.m22 = matrix1.m21 * matrix2.m12 + matrix1.m22 * matrix2.m22 + matrix1.m23 * matrix2.m32 + matrix1.m24 * matrix2.m42; matrix3.m23 = matrix1.m21 * matrix2.m13 + matrix1.m22 * matrix2.m23 + matrix1.m23 * matrix2.m33 + matrix1.m24 * matrix2.m43; matrix3.m24 = matrix1.m21 * matrix2.m14 + matrix1.m22 * matrix2.m24 + matrix1.m23 * matrix2.m34 + matrix1.m24 * matrix2.m44; matrix3.m31 = matrix1.m31 * matrix2.m11 + matrix1.m32 * matrix2.m21 + matrix1.m33 * matrix2.m31 + matrix1.m34 * matrix2.m41; matrix3.m32 = matrix1.m31 * matrix2.m12 + matrix1.m32 * matrix2.m22 + matrix1.m33 * matrix2.m32 + matrix1.m34 * matrix2.m42; matrix3.m33 = matrix1.m31 * matrix2.m13 + matrix1.m32 * matrix2.m23 + matrix1.m33 * matrix2.m33 + matrix1.m34 * matrix2.m43; matrix3.m34 = matrix1.m31 * matrix2.m14 + matrix1.m32 * matrix2.m24 + matrix1.m33 * matrix2.m34 + matrix1.m34 * matrix2.m44; matrix3.m41 = matrix1.m41 * matrix2.m11 + matrix1.m42 * matrix2.m21 + matrix1.m43 * matrix2.m31 + matrix1.m44 * matrix2.m41; matrix3.m42 = matrix1.m41 * matrix2.m12 + matrix1.m42 * matrix2.m22 + matrix1.m43 * matrix2.m32 + matrix1.m44 * matrix2.m42; matrix3.m43 = matrix1.m41 * matrix2.m13 + matrix1.m42 * matrix2.m23 + matrix1.m43 * matrix2.m33 + matrix1.m44 * matrix2.m43; matrix3.m44 = matrix1.m41 * matrix2.m14 + matrix1.m42 * matrix2.m24 + matrix1.m43 * matrix2.m34 + matrix1.m44 * matrix2.m44;うわぁ…となります。
一見するとすごく効率が悪そうですが、実際はこちらの方が格段に早いです。
あとは変数名の文字数を訳が分からなくならない程度に短くしてコード量を減らしてみたり、関数呼び出しを減らすように気をつけたりといった感じです。
配列を使わない方法で行列を定義した場合に一番苦労したのは、逆行列の計算。頭がおかしくなるかと思いました。まだバグが残ってるかもしれないという不安が付きまといます。
どなたかライブラリを使ってみてデバッグに協力してもらえないでしょうか。
といってもドキュメント皆無だからなぁ。早くドキュメントを作成せねば。
タグ:
この記事のURL: https://darkhorse2.0spec.jp/168/
2012/09/26(Wed) 02:13:42
canvasでWebフォントを使う / magicien
canvasでWebフォントを使う方法。まず、Webフォントを適当な場所にアップロードして、CSSにWebフォントを定義する。
@font-face {
font-family: 'Expressway';
src: url('./font/Expressway.woff') format('woff');
}
次に、JavaScriptでCanvasのコンテキストのfontにCSSで定義したfont-family(例ではExpressway)を指定する。Webフォント未対応の場合のために、代替となるフォントファミリー(例ではsans-serif)も指定しておく。
function drawString(context2D) {
context2D.font = "24px bold Expressway,sans-serif";
context2D.textAlign = "left";
context2D.textBaseline = "middle";
context2D.fillStyle = "#000000"; // black
context2D.strokeStyle = "#FFFFFF#; // white
context2D.fillText( "Hello, WebGL!" , 100, 100 );
}
CSSの"format"には、woff(Web Open Font Format)の他に、truetype、svg等が使えるらしい。
この記事のURL: https://darkhorse2.0spec.jp/167/
2012/09/25(Tue) 01:18:37
WebGLでの文字描画 / magicien
WebGLで文字を表示させようとすると、いろいろと面倒なので、そのときに使った方法。2Dの文字や図形を描画する場合、WebGLでまともに実現しようとすると、canvasのオブジェクトをもう一つ作って、字を描いて、テクスチャに貼付けて、それをレンダリングする、というような流れになるかと思います。
が、わざわざそんなことしなくても、作ったcanvasをそのままHTMLの画面上に貼付けた方が手間がかからないし、描画も早かったので、下のようなコードで3Dのcanvasの上に2Dのcanvasを同じサイズ、位置で重ねて使いました。
function create2DContext(canvas3D) {
var canvas2D = document.createElement('canvas');
canvas3D.insert( { after: canvas2D } );
Element.setStyle( canvas2D, {
position: 'absolute',
'z-index': 10
});
Position.clone( canvas3D, canvas2D );
canvas2D.width = canvas3D.width
canvas2D.height = canvas3D.height
var context2D = canvas2D.getContext('2d');
return context2D;
}
prototype.js、scriptaculousを使っているので、ソースはそのまま使えないかもですが...1つのcanvasで2Dのコンテキストと3Dのコンテキストを両方取得できれば問題無いのですが、一度どちらかのコンテキストを取得してしまうと、もう一方のコンテキストが取得できなくなってしまうため、2D用canvasと3D用canvasの2つが必要になるわけです。
この記事のURL: https://darkhorse2.0spec.jp/166/
2012/09/23(Sun) 18:06:49
メカクシティデイズ / magicien
買いました。最近ボカロの曲を聞くことが多くて、音楽はインターネットにつないで聞くものだと思っていましたが、今回ばかりは買いました。
目当ては空想フォレストのTAB譜。指弾きばっかりしていたせいで、ピックの使い方をすっかり忘れてしまった上にアコギだから夜は練習できない...
半べそかきながら右手と左手別々に練習中。
タグ:
この記事のURL: https://darkhorse2.0spec.jp/164/
2012/06/05(Tue) 02:48:39
OpenGL ES 2.0 プログラミングガイド / magicien
ふと思い出してこの本を開いてみたところ、WebGLでのClipPlaneの実現方法が載っていた。ES 1.1にはあったけど、2.0で無くなった機能をどう実装するか、という話が一通り載っていて、シェーダのプログラムもコピペしてそのまま使えるレベル。
そのうちの一つが、ユーザ定義クリップ面の話。
クリップ面の式を
Ax + By + Cz + D = 0としたとき、
v_clipPlane = (A, B, C, D)として次のシェーダを書けばOK。
( (A, B, C)はクリップ面に対する法線、Dは原点(0, 0)とクリップ面との距離になる。
例えば、Y=0平面をクリップ面としたいなら、v_clipPlane=(0,1,0,0))
頂点シェーダ:
uniform vec4 v_clipPlane;
uniform mat4 matViewProjection;
attribute vec4 rm_Vertex;
varying float v_clipDist;
void main(void)
{
v_clipDist = dot(rm_Vertex.xyz, u_clipPlane.xyz) + u_clipPlane.w;
gl_Position = matViewProjection * rm_Vertex;
}
フラグメントシェーダ:
precision mediump float;
varying float v_clipDist;
void main(void)
{
if(v_clipDist < 0.0)
discard;
gl_FragColor = vec4(0.5, 0.5, 1.0, 0.0);
}
頂点(rm_Vertex)毎にクリップ面との距離(v_clipDist)を計算しておく。
v_clipDist が 0 より小さい点はクリップ面の裏側にあることになるため、描画しない(discard)。
もっと難しい計算が必要だと思ったけど、恐ろしく簡単に実装できた。
この記事のURL: https://darkhorse2.0spec.jp/163/
2012/05/19(Sat) 22:44:29
床面反射 / magicien
このページを参考にして実装。
床面反射は今のところ、y=0平面で反射した結果(y軸のスケールを-1にした結果)を描画しているだけ。
ただ、それだと床面の枠からはみ出してしまうので、stencilを使って床があるところだけ描画するようにする。
WebGLでステンシルバッファを使う場合は、getContextをするときにオプションを指定する必要がある。
var canvas = $('canvas');
var context = canvas.getContext('webkit-3d', {stencil: true});
あとはOpenGLと同様。以下、今回使った描画の流れの個人的メモ。
1.Color、Depth、Stencilの各バッファをクリア
2.Color有効、Depth有効、Stencil有効(Always 1に上書き)にして床面を描画
3.Color有効、Depth有効、Stencil有効(Always 0に上書き)にして床面以外を描画
4.Color無効、Depth有効(rangeを1〜1に指定)、Stencil有効(1の箇所のみ描画、値は変更せず)にして床面を描画
5.scale(1, -1, 1)でY=0平面で反射、カリング指定をしている場合はFrontとBackを入れ替え
6.Color有効(blendFunc(ONE、ZERO) →元のAlpha値を気にせず上書き)、Depth有効、Stencil有効(1の箇所のみ描画、値は変更せず)にして床面以外をRGBAそれぞれの値を70%にして描画
7.scale、カリング指定を元に戻す
8.Color有効(blendFunc(ONE_MINUS_DST_ALPHA, DST_ALPHA)→元のAlpha値が100%なら描画しない、70%ならAlpha30%で描画)、Depth有効、Stencil有効(1の箇所のみ描画、値は変更せず)にして床面を描画
問題点
・ClipPlaneが使えないので、床面の裏側のオブジェクトが描画されてしまう。自力で実装するか...
・6&8のStencilの指定方法は改善できそう。
・6のAlpha値の指定が悪いらしく、Alpha値を持つテクスチャがうまく描画されない
・そもそもAlpha値が1.0じゃない部分はzソートした上で最後に描画しないといけない
タグ:
この記事のURL: https://darkhorse2.0spec.jp/161/
2012/05/10(Thu) 02:11:55
GWのあれこれ / magicien
見てきたといっても、関係者しか中に入れないようなので、外から眺めてきただけですが。
東京スカイツリー周辺は再開発が進んでいるのだろうと思いきや、そんな雰囲気はありませんでした。
今回入れなかったツリーの1階部分がこれから充実していくのかもしれません。
上野から浅草を通ってスカイツリーに行く途中に立ち寄ったのが、神谷バーというところ。 昼過ぎでしたが恐ろしい程繁盛しており、お好きな席にどうぞ、と言われても空席が無くてしばらく立ち往生。見かねたおじさんに手招きされて、もうすぐ立つからここに座りなよと席を譲ってもらいました。
前に読んだ本に同じような名前の飲み物が出てきたような気がすると思い、電気ブランなるものを注文しました。
見たところ梅酒のようで甘い印象でしたが、飲んでみると普通に強いお酒で、ブランデーに少しサイダーを混ぜたような感じ。デンキブランFIXというものもありましたが、こちらは甘くてさわやかなカクテルでした。
タグ:
この記事のURL: https://darkhorse2.0spec.jp/160/
2012/05/06(Sun) 22:30:32





