<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2japanesefull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>フリップフラップ</title>
	
	<link>http://blog.flup.jp</link>
	<description>Webサービスやシステム開発の技術メモ</description>
	<pubDate>Tue, 02 Mar 2010 05:51:54 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/flipflup" /><feedburner:info uri="flipflup" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Parallels Desktopでブリッジが使えない場合の対処</title>
		<link>http://feedproxy.google.com/~r/flipflup/~3/XW1fH5NqDzE/</link>
		<comments>http://blog.flup.jp/2010/03/02/parallels-desktop-how-to-fix-bridge-network/#comments</comments>
		<pubDate>Tue, 02 Mar 2010 05:51:12 +0000</pubDate>
		<dc:creator>flipper</dc:creator>
		
		<category><![CDATA[一般]]></category>

		<guid isPermaLink="false">http://blog.flup.jp/?p=428</guid>
		<description><![CDATA[

ものすごく久々の更新です。
最近使用している環境は専らMacで、VirtualBoxではなく開発環境もParallels Desktop上のLinuxを使うことが多くなりました。

EnableSendFileの設定 [...]]]></description>
			<content:encoded><![CDATA[<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2010/03/parallels.jpg" alt="parallels" title="parallels" width="209" height="157" class="alignnone size-full wp-image-427" /></div>
<p>ものすごく久々の更新です。</p>
<p>最近使用している環境は専らMacで、VirtualBoxではなく開発環境もParallels Desktop上のLinuxを使うことが多くなりました。</p>
</div>
<p>EnableSendFileの設定などはもちろんVirtualBox同様必要なのですが、それ以前の問題としてアップデートを行ったところネットワークをブリッジに設定すると接続できなくなってしまいました&#8230;。</p>
<p>いろいろ調べたところ、設定ファイルを修正することで接続できるようになりました！その方法は以下の通りです。</p>
<p><span id="more-428"></span></p>
<h3>config.pvs</h3>
<p>まず、仮想マシンのファイルがあるフォルダをFinderで開きます。標準では、書類の中のParallelsフォルダになるかと思います。</p>
<p>次に、対象となる仮想マシンのファイル（.pvmファイル）を右クリックし、<strong>「パッケージの内容を表示」</strong>を選びます。</p>
<p>その中のconfig.pvsをテキストエディタで開きます。</p>
<p>そのうち、以下のような記述があるはずなので、その部分を変更します。</p>
<pre class="prettyprint">
&lt;NetworkAdapter&gt;
...
&lt;ForceHostMacAddress&gt;1&lt;/ForceHostMacAddress&gt;
&lt;DHCPUseHostMac&gt;0&lt;/DHCPUseHostMac&gt;
...
&lt;/NetworkAdapter&gt;
</pre>
<p>私の環境では上記設定のみでうまくいきましたが、それでもだめな場合はDHCPUseHostMacも1に設定してみてください。</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/flipflup?a=XW1fH5NqDzE:UnUccrsCA9g:OAQBO0PjnPA"><img src="http://feeds.feedburner.com/~ff/flipflup?d=OAQBO0PjnPA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.flup.jp/2010/03/02/parallels-desktop-how-to-fix-bridge-network/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.flup.jp/2010/03/02/parallels-desktop-how-to-fix-bridge-network/</feedburner:origLink></item>
		<item>
		<title>DocumentRootに共有フォルダを使った場合の問題</title>
		<link>http://feedproxy.google.com/~r/flipflup/~3/mLSzkJ6Mn7M/</link>
		<comments>http://blog.flup.jp/2009/04/06/problem_of_using_shared_folder_to_document_root/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 12:12:54 +0000</pubDate>
		<dc:creator>flipper</dc:creator>
		
		<category><![CDATA[一般]]></category>

		<guid isPermaLink="false">http://blog.flup.jp/?p=419</guid>
		<description><![CDATA[

VirtualBoxにCentOSなどのLinux環境を構築し、そこへApacheやらデータベースサーバやらをインストールしてWebアプリの開発を行うことがよくあります。
その際に、ホストのディレクトリを共有フォルダ [...]]]></description>
			<content:encoded><![CDATA[<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2009/04/virtualbox.jpg" alt="virtualbox" title="virtualbox" width="220" height="220" class="alignnone size-full wp-image-421" /></div>
<p>VirtualBoxにCentOSなどのLinux環境を構築し、そこへApacheやらデータベースサーバやらをインストールしてWebアプリの開発を行うことがよくあります。</p>
<p>その際に、ホストのディレクトリを共有フォルダ設定してマウントパスをApacheのDocumentRootに指定すると便利に開発できるかと思います。</p>
</div>
<p>・・・が、しかし、今日その設定を行ってみてブラウザで表示を確認してみたところ、なぜか静的コンテンツがまともに表示されません・・・。</p>
<p>まっしろになってしまったり、更新したはずなのに古いものが表示されたり・・・。一体原因はなんなんでしょうか。。<br />
<span id="more-419"></span></p>
<h3>EnableSendfile</h3>
<p>Apacheの設定ファイル、httpd.confのcache関係のモジュールをオフにしたりといろいろとやってみましたが、全く変化ありません。</p>
<p>あきらめかけていたのですが、Live HTTP Headersでヘッダを見てみたところ、静的コンテンツが、206 Partial Content というレスポンスになっていることが分かりました。</p>
<p>このレスポンスコードをたよりに色々と検索してみると、どうやら EnableSendfile ディレクティブをオフにすればよいらしいことが分かりました。</p>
<p>さらに、このディレクティブについて調べてみると、</p>
<blockquote><p>ネットワークマウントされた DocumentRoot  (例えば NFS や SMB) では、カーネルは自身のキャッシュを使ってネットワークからのファイルを 送ることができないことがあります。</p></blockquote>
<p>とあり、まさに今の症状の通りでしたので設定してみると・・・。</p>
<p>うまくいきました！！</p>
<p>もし、同じような状況に直面している人がいたらお役に立てば嬉しいです。</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/flipflup?a=mLSzkJ6Mn7M:pjCPN8NfUAQ:OAQBO0PjnPA"><img src="http://feeds.feedburner.com/~ff/flipflup?d=OAQBO0PjnPA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.flup.jp/2009/04/06/problem_of_using_shared_folder_to_document_root/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.flup.jp/2009/04/06/problem_of_using_shared_folder_to_document_root/</feedburner:origLink></item>
		<item>
		<title>Ubuntuでソースから.debの生成方法</title>
		<link>http://feedproxy.google.com/~r/flipflup/~3/ogmETJytb6o/</link>
		<comments>http://blog.flup.jp/2009/03/20/building_dev_from_source_in_ubunt/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 15:20:00 +0000</pubDate>
		<dc:creator>flipper</dc:creator>
		
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://blog.flup.jp/?p=410</guid>
		<description><![CDATA[

普段、会社ではUbuntu 8.10を使っているのですが、なぜかFirefoxが遅い・・・。Firefoxが、というよりかはFirefoxで動かすJavascriptが遅い感じなのです。
ちょっと遅い感じがする、とい [...]]]></description>
			<content:encoded><![CDATA[<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/ubuntu.jpg" alt="ubuntu" title="ubuntu" width="230" height="180" class="alignnone size-full wp-image-411" /></div>
<p>普段、会社ではUbuntu 8.10を使っているのですが、なぜかFirefoxが遅い・・・。Firefoxが、というよりかはFirefoxで動かすJavascriptが遅い感じなのです。</p>
<p>ちょっと遅い感じがする、というレベルではなくAjaxを多用しているサイトとかだと止まるんじゃないかと思うほど分かりやすい遅さです。</p>
</div>
<p>調べてみると、ipv6系のネットワークの遅延についての記事はたくさん出るのですが、Javascriptが遅いという話はなかなか見つかりませんでした。</p>
<p>ビルドオプションがおかしいのかな？と思って、最適化ビルドされた<a href="http://getswiftfox.com/">Swiftfox</a>を試してみることも考えたのですがバージョンが3.0.4系で止まってしまっているので、自分でビルドしてみることにしました。</p>
<p><span id="more-410"></span></p>
<h3>apt-getを駆使する</h3>
<p>Ubuntuはdebian系のディストリビューションなので、ソースからビルドし最終的には.debファイルにしてパッケージ化しておき、公式リポジトリ側がバージョンアップしたら更新できるようにしたいと思います。</p>
<p>まず、ソースコードの取得について。</p>
<p>普通ソースコードは公式サイトからtarボールやsvn, cvsなどのバージョン管理ツールで取ってくることが多いと思いますが、debパッケージ管理されているアプリのソースは、以下のコマンドで取得できます。</p>
<p>カレントディレクトリにいろいろ展開されるので、専用にディレクトリを作成し、その中で行った方が良いです。</p>
<div class="terminal">
<ul>
<li>apt-get source firefox</li>
</ul>
</div>
<p>また、このソースをビルドするために必要なパッケージを一括でインストールすることもできます。</p>
<div class="terminal">
<ul>
<li>sudo apt-get build-dep firefox</li>
</ul>
</div>
<h3>debuild</h3>
<p>ビルドには、debuildというツールを使うのですが、この辺がちょっとややこしかったです。</p>
<p>apt-get sourceでソースを取ってくると、前述のように色々とファイルを取得して新しくディレクトリが作成されます。この中にソースやらが入っているのですが、debianというサブディレクトリができていると思います。</p>
<p>この、debianの中に重要なファイルとして、ビルドオプションなどが定義されたrules、バージョン情報が書かれたchangelog、依存関係が定義されたcontrolなどが存在していると思います。</p>
<p>まずはrulesを編集してビルドオプションを変更します（以下は変更箇所のみ）。</p>
<pre class="prettyprint">
CFLAGS = -g -O3 -march=native
CXXFLAGS = -g -O3 -march=native

#
#   (中略)
#

    -enable-optimize="-O3 -w -march=native" ¥
</pre>
<p>そして、changelogの編集ですが、これはコマンドで行うことができますが、それにはdevscriptsパッケージが必要なのでインストールしておきます。</p>
<div class="terminal">
<ul>
<li>sudo apt-get install devscripts</li>
</ul>
</div>
<p>次に編集用のコマンドを実行しますが、これはdebianディレクトリの親ディレクトリをカレントにして行う必要があります（そうしないと、debian/changelogが無いと怒られます）。</p>
<div class="terminal">
<ul>
<li>debchange -i</li>
</ul>
</div>
<p>debchangeを起動するとエディタの選択肢が出るので好みのものを選びます（私は1のviにしました）。</p>
<p>とりあえず、何もせずに保存してしまっても特に問題はないですが、分かりやすいようにコメントを入れたり、リポジトリが更新するであろうバージョン番号の採番方法と重複しないように修正を入れます（バージョンについては、一つ下のバージョンがリポジトリの最新バージョンなので、それに -0 とかを付加したものにしておけばいいかと思います）。</p>
<p>ここまでで一応準備は整ったので、最後にビルドコマンドを実行します。</p>
<div class="terminal">
<ul>
<li>debuild -us -uc</li>
</ul>
</div>
<p>しばらく時間が掛かると思いますが、そのうちプロンプトに戻るはずです。もしエラーが出たら、failedとか出ているはずなので・・・その時はrulesかchangelog（たぶんrulesのほう）の記述が間違っている箇所があるので修正後再度実行します。</p>
<h3>debのインストール</h3>
<p>ビルドが終わると、最初の作業ディレクトリ（今まで作業していたところの親ディレクトリ）に移動するとたくさんのdebファイルができていると思います。</p>
<p>Firefoxの場合は、firefox-3.0_3.0.7+nobinonly-0ubuntu0.8.10.1-0_i386.deb（バージョン番号によってファイル名が違います）というファイルが本体で、あとfirefox-3.0-gnome-supportとfirefox-3.0-brandingの2つのパッケージも入れておかないと依存関係が壊れているとか言われてしまうので要注意です。</p>
<p>インストールは普通のdeb同様、</p>
<div class="terminal">
<ul>
<li>sudo dpkg -i firefox-3.0_3.0.7+nobinonly-0ubuntu0.8.10.1-0_i386.deb</li>
</ul>
</div>
<p>という感じでいけます。</p>
<h3>インストールしたが・・・</h3>
<p>さて、上記でビルド済みのパッケージをインストールできたはずなんですが・・・。about:buildconfigを見てみても、ビルドオプションが全く変化なしでした。。。orz</p>
<p>速度的にも大して変化はないようなので正しくインストールできているのかどうか謎です。ただ、ビルド中のコマンドラインオプションに追加した最適化オプションなどは入っていたのは確認できたんですが・・・。</p>
<p>うーん、どういうことでしょう・・・？(?_?)</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/flipflup?a=ogmETJytb6o:-kh_WfDr_j4:OAQBO0PjnPA"><img src="http://feeds.feedburner.com/~ff/flipflup?d=OAQBO0PjnPA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.flup.jp/2009/03/20/building_dev_from_source_in_ubunt/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.flup.jp/2009/03/20/building_dev_from_source_in_ubunt/</feedburner:origLink></item>
		<item>
		<title>PHPで簡単にグラフが作れるライブラリ</title>
		<link>http://feedproxy.google.com/~r/flipflup/~3/pcjq_8kn2KI/</link>
		<comments>http://blog.flup.jp/2009/03/18/easy_using_library_to_create_charts_for_php/#comments</comments>
		<pubDate>Wed, 18 Mar 2009 07:03:15 +0000</pubDate>
		<dc:creator>flipper</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.flup.jp/?p=379</guid>
		<description><![CDATA[

PHPを使って、アクセス解析結果やアンケートの集計結果などグラフを表示したいという機会は結構あるのではないかと思います。
しかし、何もないところからこれを作ろうとするとかなり骨が折れる上に、美しいグラフを作成するのは [...]]]></description>
			<content:encoded><![CDATA[<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/chart.png" alt="chart" title="chart" width="230" height="150" class="alignnone size-full wp-image-380" /></div>
<p>PHPを使って、アクセス解析結果やアンケートの集計結果などグラフを表示したいという機会は結構あるのではないかと思います。</p>
<p>しかし、何もないところからこれを作ろうとするとかなり骨が折れる上に、美しいグラフを作成するのは難しいのではないかと思います。
</p></div>
<p>今回はオープンソースのライブラリを使って、比較的簡単にグラフを作成してみたいと思います。<br />
<span id="more-379"></span></p>
<h3><a href="http://pchart.sourceforge.net/index.php">pChart</a></h3>
<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/pchart.png" alt="pchart" title="pchart" width="380" height="200" class="alignnone size-full wp-image-386" /></div>
</div>
<p>まずは<a href="http://pchart.sourceforge.net/index.php">pChart</a>というライブラリから。これはGPLライセンスのライブラリで、サーバサイドで画像を生成するタイプのものになります。動作には、GDサポートを有効にしたPHPが必要となります。</p>
<p>対応しているグラフの種類は、</p>
<ul>
<li>折れ線グラフ</li>
<li>3次スプライン曲線</li>
<li>プロットチャート</li>
<li>棒グラフ</li>
<li>パイチャート</li>
</ul>
<p>と、豊富に対応していて、生成されるグラフの品質もかなり高いです。</p>
<p>このライブラリは、データを表すpDataとグラフを表すpChartという二つのクラスを使って描画を行います。使い方は以下のような感じです（サンプルをちょっとだけ変えたものです）。</p>
<pre class="prettyprint">
&lt;?php
 // Standard inclusions
 include("pChart/pData.class");
 include("pChart/pChart.class");  

 // Dataset definition
 $DataSet = new pData;
 $DataSet-&gt;AddPoint(array(10,2,3,5,3),"Serie1");
 $DataSet-&gt;AddPoint(array("1月","2月","3月","4月","5月"),"Serie2");
 $DataSet-&gt;AddAllSeries();
 $DataSet-&gt;SetAbsciseLabelSerie("Serie2");  

 // Initialise the graph
 $Test = new pChart(380,200);
 $Test-&gt;setFontProperties("Fonts/VL-PGothic-Regular.ttf",8);
 $Test-&gt;drawFilledRoundedRectangle(7,7,373,193,5,240,240,240);
 $Test-&gt;drawRoundedRectangle(5,5,375,195,5,230,230,230);  

 // Draw the pie chart
 $Test-&gt;setFontProperties("Fonts/VL-PGothic-Regular.ttf",8);   

$Test-&gt;drawPieGraph($DataSet-&gt;GetData(),$DataSet-&gt;GetDataDescription(),150,90,110,PIE_PERCENTAGE,TRUE,50,20,5);
 $Test-&gt;drawPieLegend(310,15,$DataSet-&gt;GetData(),$DataSet-&gt;GetDataDescription(),250,250,250);  

 $Test-&gt;Render("pchart.png");
</pre>
<p>日本語を表示するためには、setFontProperties() で日本語に対応したフォントを指定する必要があります。メソッドに渡す文字列のエンコーディングをUTF-8にしておけば、表示されるはずです。</p>
<p>このライブラリの面倒な点は、画像サイズはいいとしても、描画するグラフの座標をすべて細かく指定する必要があるところです。全体の大きさを変えたい、という時はすべてのパラメータを変更していくか、あらかじめ各パラメータの数値を最初のpChartのサイズに対する割合（または差分）で変数に入れておくかしなければなりません。</p>
<p>計算でパラメータを求めるように変更したソースは以下のようになります。</p>
<pre class="prettyprint">
&lt;?php
 // Standard inclusions
 include("pChart/pData.class");
 include("pChart/pChart.class");  

 define("CHART_WIDTH", 380);
 define("CHART_HEIGHT", 200);

 define("CHART_MARGIN", 5);

 // Dataset definition
 $DataSet = new pData;
 $DataSet-&gt;AddPoint(array(10,2,3,5,3),"Serie1");
 $DataSet-&gt;AddPoint(array("1月","2月","3月","4月","5月"),"Serie2");
 $DataSet-&gt;AddAllSeries();
 $DataSet-&gt;SetAbsciseLabelSerie("Serie2");  

 // Initialise the graph
 $Test = new pChart(CHART_WIDTH,CHART_HEIGHT);
 $Test-&gt;setFontProperties("Fonts/VL-PGothic-Regular.ttf",8);
$Test-&gt;drawFilledRoundedRectangle(CHART_MARGIN+2,CHART_MARGIN+2,CHART_WIDTH-CHART_MARGIN-2,CHART_HEIGHT-CHART_MARGIN-2,CHART_MARGIN,240,240,240);
 $Test-&gt;drawRoundedRectangle(CHART_MARGIN,CHART_MARGIN,CHART_WIDTH-CHART_MARGIN,CHART_HEIGHT-CHART_MARGIN,CHART_MARGIN,230,230,230);  

 // Draw the pie chart
 $Test-&gt;setFontProperties("Fonts/VL-PGothic-Regular.ttf",8);
$Test-&gt;drawPieGraph($DataSet-&gt;GetData(),$DataSet-&gt;GetDataDescription(),CHART_MARGIN*10+(CHART_WIDTH-CHART_MARGIN*10)/3,CHART_HEIGHT/2-CHART_MARGIN*2,(CHART_WIDTH-CHART_MARGIN*10)/3,PIE_PERCENTAGE,TRUE,50,20,5);
 $Test-&gt;drawPieLegend(CHART_WIDTH-CHART_MARGIN*14,CHART_MARGIN*3,$DataSet-&gt;GetData(),$DataSet-&gt;GetDataDescription(),250,250,250);  

 //$Test-&gt;Render("pcharat.png");
 // direct output image
 $Test-&gt;Stroke();
</pre>
<p>これで、defineしている数値を変えるだけで全体の大きさが変わります。しかし、あまり直感的でないしコードが読みづらいですね・・。上記をラップしたメソッドを用意して自動的に値を伸縮させるとスッキリしそうですが。</p>
<p>あと、このライブラリの特徴としてpCacheクラスというのを使うことでデータをキャッシングして高速化することができるようです。</p>
<h3><a href="http://teethgrinder.co.uk/open-flash-chart-2/">Open Flash Chart</a></h3>
<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/ofc.png" alt="ofc" title="ofc" width="350" height="200" class="alignnone size-full wp-image-394" />
</div>
</div>
<p>これはLGPLのグラフライブラリで、Flashをつかった描画ができます。JSONを使ったデータをFlashに受け渡す構造になっているため、基本的にサーバサイドの言語はなんでも使えると思います。</p>
<p>グラフの種類は、</p>
<ul>
<li>折れ線グラフ</li>
<li>棒グラフ（スタイルが何種類か）</li>
<li>エリアグラフ</li>
<li>パイチャート</li>
<li>散布図</li>
<li>レーダーチャート</li>
</ul>
<p>が使えるようです。描画部分はFlashなのでグラフの種類によってはアニメーションさせることもできます。</p>
<p>用意されているクラスライブラリはPHPのほか、</p>
<ul>
<li>Ruby</li>
<li>.Net</li>
<li>Perl</li>
<li>Java</li>
<li>Python</li>
<li>Google WebToolkit</li>
</ul>
<p>と、多くの言語に対応されています。</p>
<p>このライブラリは、前述のとおりデータをJSONで受け渡すので、サーバサイドでのJSON生成コードとFlashへ受け渡すためのJavascriptコードの2つが必要となります。</p>
<p>まず、JSON生成部分は以下のようになります。</p>
<pre class="prettyprint">
// ランダム値のデータを用意
srand((double)microtime()*1000000);
$data = array();
for( $i=0; $i<10; $i++ )
  $data[] = rand(2,9);

require_once('OFC/OFC_Chart.php');

$title = new OFC_Elements_Title("テスト");

// ここのオブジェクトの選び方でグラフの種類が決定される
$bar = new OFC_Charts_Bar_3d();
$bar-&gt;set_values( $data );
$bar-&gt;colour = '#D54C78';

$x_axis = new OFC_Elements_Axis_X();
$x_axis-&gt;set_3d( 5 );
$x_axis-&gt;colour = '#909090';
$x_axis-&gt;set_labels( array(1,2,3,4,5,6,7,8,9,10) );

$chart = new OFC_Chart();
$chart-&gt;set_title( $title );
$chart-&gt;add_element( $bar );
$chart-&gt;set_x_axis( $x_axis );
</pre>
<p>上の例では、OFC_Charts_Bar_3d クラスを使っていますが、これを変更することによってグラフの種類をいろいろと変えることができます。</p>
<p>Javascript側はJSONデータを設定して決められた関数でFlashに受け渡すだけです。</p>
<pre class="prettyprint">
<!-- 必ずこのライブラリが必要 -->
&lt;script type="text/javascript" src="js/json/json2.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
function open_flash_chart_data()
{
    return JSON.stringify(data);
}

// toPrettyString() メソッドでJSON形式のコードがreturnされてくる
var data = &lt;?php echo $chart->toPrettyString(); ?&gt;;
&lt;/script&gt;
</pre>
<p>また、上記のようにスクリプトベースで値をセットするのではなく、あらかじめJSON形式のデータをファイルに入れておき、GETパラメータで ?ofc=ファイル名 としても読み込むことができるようです。ファイル名のところはphpのようなサーバサイド生成できるスクリプトでもOKなので、同じグラフでデータだけ切り替えたい場合等に便利に使えそうです。</p>
<h3><a href="http://code.google.com/intl/ja/apis/chart/">Google Chart API</a></h3>
<p>Googleが公開しているグラフ生成APIです。自サーバへの負荷なし、プログラミングの知識もなしでグラフが使えるというのが最大のメリットでしょうか。</p>
<p>このAPIを<a href="http://luddep.se/notebook/2008/04/13/charts-php-and-google-charts-api/">PHPでさらに簡単に扱うことができるクラスライブラリ</a>を発見したので、使ってみることにしました。</p>
<p>使い方は本当に簡単で、以下のように書くだけです（最初の画像のような表示になります）。</p>
<pre class="prettyprint">
include( 'GoogChart.class.php' );

/** Create chart */
$chart = new GoogChart();

// Set graph data
$data = array(
			'IE' =&gt; 46.94,
			'Firefox' =&gt; 40.68,
			'Safari' =&gt; 4.32,
			'Chrome' =&gt; 4.22,
			'Opera' =&gt; 3.03,
			'その他' =&gt; 0.78
		);

// Set graph colors
$color = array(
			'#99C754',
			'#54C7C5',
			'#999999',
		);

// Setup chart attributes
$chart-&gt;setChartAttrs( array(
	'type' =&gt; 'pie',
	'title' =&gt; 'ブラウザ利用比率',
	'data' =&gt; $data,
	'size' =&gt; array( 230, 150 ),
	'color' =&gt; $color
	));

// Print chart
echo $chart;
</pre>
<p>連想配列のデータを作ってグラフのインスタンスに渡すだけで、以下のようなGoogle Chart API用の img タグが生成されます。</p>
<blockquote><p>
http://chart.apis.google.com/chart?cht=p&#038;chtt=%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E5%88%A9%E7%94%A8%E6%AF%94%E7%8E%87&#038;chd=t%3A46.94%2C40.68%2C4.32%2C4.22%2C3.03%2C0.78&#038;chl=IE%7CFirefox%7CSafari%7CChrome%7COpera%7C%E3%81%9D%E3%81%AE%E4%BB%96&#038;chs=230&#215;150&#038;chco=99C754%2C54C7C5%2C999999&#038;chm=&#038;chf=a%2Cs%2Cffffff
</p></blockquote>
<p>今回紹介したライブラリは3種類とも、それぞれ特徴が異なるので用途によって使い分けるのがいいかな、と思います。</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/flipflup?a=pcjq_8kn2KI:FGCVVHVxkLM:OAQBO0PjnPA"><img src="http://feeds.feedburner.com/~ff/flipflup?d=OAQBO0PjnPA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.flup.jp/2009/03/18/easy_using_library_to_create_charts_for_php/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.flup.jp/2009/03/18/easy_using_library_to_create_charts_for_php/</feedburner:origLink></item>
		<item>
		<title>Flash Player 10 の3D機能に足りないもの</title>
		<link>http://feedproxy.google.com/~r/flipflup/~3/nJ4d81b3BWk/</link>
		<comments>http://blog.flup.jp/2009/03/16/shortage_of_the_3d_functions_in_fp10/#comments</comments>
		<pubDate>Sun, 15 Mar 2009 17:47:15 +0000</pubDate>
		<dc:creator>flipper</dc:creator>
		
		<category><![CDATA[3D]]></category>

		<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://blog.flup.jp/?p=364</guid>
		<description><![CDATA[

ここ数日、Astro (FP10) の3D機能をいろいろやってみてるのですが、Matrix関係やdrawTriangles()メソッドによって確かに便利になっていると思います。
しかし、3Dプログラミングをしようと思 [...]]]></description>
			<content:encoded><![CDATA[<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/ball.jpg" alt="ball" title="ball" width="249" height="249" class="alignnone size-full wp-image-367" /></div>
<p>ここ数日、Astro (FP10) の3D機能をいろいろやってみてるのですが、Matrix関係やdrawTriangles()メソッドによって確かに便利になっていると思います。</p>
<p>しかし、3Dプログラミングをしようと思うと必ず必要な、ある重要な機能が抜けているのです・・・。
</p></div>
<p>上は、私が試しにつくった球の3D表示のswfをキャプチャしたものですが、その機能がないおかげで、これだけでもかなり大変でした。。<br />
<span id="more-364"></span></p>
<h3>シェーディング機能が全く用意されていない</h3>
<p>実は、Flash Player10の3D機能にはシェーディング（3Dプログラミングにおいての）の機能が全く用意されていないのです。</p>
<p>これはどういうことかというと、DirectXやOpenGLなどの一般的な3DのAPIでは標準で用意されている光源やその光源によってどのような色で各ピクセルを出力するかといった計算を行う機能がAstroにはないということです。つまり、シェーディング部分を自前で実装する必要があります。</p>
<p>3Dのシェーディングは一般的なものにフラットシェーディング、グーローシェーディング、フォンシェーディングなどがありますが、これらをAction Scriptで実装するにはどうすればよいか、ちょっと考えてみました。</p>
<h3>フラットシェーディング</h3>
<p>フラットシェーディングとは面単位で色が決定されるシェーディング方法で、面法線をもとにランバート反射を計算するものです。</p>
<p>これは、三角形を描画する毎にbeginFill()でその色を塗ればよさそうです。三角形ごとに色がことなるので、今回追加されたdrawTriangles()は使えないと思います。</p>
<h3>グーローシェーディング</h3>
<p>これは、頂点単位の法線を用いて頂点毎のランバート反射を計算し、各頂点間の色を線形補完することによるシェーディング方法です。</p>
<p>これについては、beginGradiantFill()でいけるのかな？パラメータを見る限りちょっと難しそう・・・。ひょっとしたらbeginShaderFill()とかを使わないと無理かも。</p>
<h3>フォンシェーディング</h3>
<p>これは頂点単位の法線を補完してピクセル単位で法線をもとにランバート反射やフォンの鏡面反射モデルを適用するものですが、まともに計算するのはまず無理です（パフォーマンス的に計算量が多くなりすぎる）。</p>
<p>全く方法が思いつかなかったのですがPapervision3Dでは実現できてるみたいなので、ソースを見てみたところ、やはりまともなやり方を正面からやるのではなくライトマップで近似しているようです。</p>
<p>ライトマップとは、ライティングの計算を省略するためにテクスチャにライト情報をもたせてそれをもとに色をつける方法で、具体的にはテクスチャマッピングを行った後、このライトマップテクスチャを乗算します。</p>
<h3>今回作ったもの</h3>
<p>今回は、テクスチャマッピングが面倒だった（UVの用意とかが要るので・・）ので、ライトマップ自体に色をつけてそれっぽくしてみました。</p>
<p>ライトマップのビットマップデータの生成は以下のような感じでやっています（ほぼPapervisionのまんま・・）。</p>
<pre class="prettyprint">
    public function makeLightMap(lightColor:int, diffuseColor:int, ambientColor:int, specularLevel:int):BitmapData
    {
      var w:Number = 1024;
      var mat:Matrix = new Matrix();
      var s:Sprite = new Sprite();
      mat.createGradientBox(w,w,0,0,0);

      s.graphics.beginGradientFill(GradientType.RADIAL, [lightColor,diffuseColor,ambientColor],
         [1,1,1], [0,255-specularLevel, 255], mat);
      s.graphics.drawRect(0,0,w,w);
      s.graphics.endFill();

      var bmp:BitmapData = new BitmapData(w,w,false,0x0000ff);
      bmp.draw(s);

      return bmp;
    }
</pre>
<p>放射状のグラデーションを使って、スペキュラハイライト〜ディフューズ色の減衰のようになるようにしています（全然正確ではないので、あくまでそれっぽい感じです＾＾；）。</p>
<p>これをどうやって物体に貼り付けるか、ですが、光線ベクトルと視線ベクトルのハーフベクトルを計算して、そのハーフベクトルの先から物体を見たときの法線ベクトルの位置をテクスチャ座標としてサンプリングしています（意味わかるかな・・）。ハーフベクトルを正規化した座標を視点とする行列を生成して、その行列で法線ベクトルを変換しているわけです。</p>
<pre class="prettyprint">
    public function calcUV(mat:Matrix3D):void
    {
      uvts = new Vector.&lt;Number&gt;();
      for(var index:int = 0; index &lt; vertices.length; index+=3)
      {
        var vertex:Vector3D = new Vector3D(vertices[index], vertices[index+1], vertices[index+2]);
        vertex = mat.transformVector(vertex);
        vertex.normalize(); // -1 〜 1 の範囲に

        uvts.push((vertex.x + 1.0) / 2.0);
        uvts.push((vertex.y + 1.0) / 2.0);
        uvts.push(1.0); // t は仮の値を入れる
      }
    }
</pre>
<p>こんな感じです。</p>
<p>ちょっと、環境によっては重いかもしれないのでswfを貼るのは今回はやめておきます。ソースは以下からダウンロードできるので興味がある方は見てみてください。<br />
<a class="attached" href='http://blog.flup.jp/wp-content/uploads/2009/03/astro_phong.zip'>astro_phong.zip</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/flipflup?a=nJ4d81b3BWk:_pEwrHkGfV0:OAQBO0PjnPA"><img src="http://feeds.feedburner.com/~ff/flipflup?d=OAQBO0PjnPA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.flup.jp/2009/03/16/shortage_of_the_3d_functions_in_fp10/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.flup.jp/2009/03/16/shortage_of_the_3d_functions_in_fp10/</feedburner:origLink></item>
		<item>
		<title>Pixel BenderのblendShader使用時の謎</title>
		<link>http://feedproxy.google.com/~r/flipflup/~3/ElmY6sFMZXM/</link>
		<comments>http://blog.flup.jp/2009/03/14/pixel-bender_with_blendshader/#comments</comments>
		<pubDate>Fri, 13 Mar 2009 17:49:05 +0000</pubDate>
		<dc:creator>flipper</dc:creator>
		
		<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://blog.flup.jp/?p=348</guid>
		<description><![CDATA[

以前紹介したバンプマッピングのPixel BenderをFlashで使おうとしてみたのですが、なぜかうまくいきませんでした・・・。
真っ黒でなにもでなかったり、明らかにおかしな色になってしまったのです。その際、色々試 [...]]]></description>
			<content:encoded><![CDATA[<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/result1.jpg" alt="result1" title="result1" width="200" height="200" class="alignnone size-full wp-image-350" /></div>
<p>以前紹介したバンプマッピングのPixel BenderをFlashで使おうとしてみたのですが、なぜかうまくいきませんでした・・・。</p>
<p>真っ黒でなにもでなかったり、明らかにおかしな色になってしまったのです。その際、色々試した結果をここでちょっと報告したいと思います。
</p></div>
<p>まずは、上の画像がいったいなんなのかを説明します。<br />
<span id="more-348"></span></p>
<h3>outCoord()の値を可視化する</h3>
<p>上の画像は、outCoord()の値からx座標の値をR成分に、y座標の値をG成分にしたものです。</p>
<p>これには、以下のPixel Benderのコードを使っています。</p>
<pre class="prettyprint">
&lt;languageVersion : 1.0;&gt;

kernel SampleFilter
&lt;   namespace : "jp.flup";
    vendor : "Flup Inc.";
    version : 1;
    description : "outCoord test filter";
&gt;
{
    input image4 src;
    output pixel4 dst;

    void
    evaluatePixel()
    {
        dst.r = (outCoord().x-100.0)/200.0;
        dst.g = (100.0-outCoord().y)/200.0;
        dst.b = 0.0;
        dst.a = 1.0;
    }
}
</pre>
<p>これは、Pixel Bender Toolkit で生成した画像を出力したもので、Flashはこの時点では関係ありません。</p>
<h3>ShaderFilterの適用</h3>
<p>次に、ShaderFilterで単一の入力イメージに対してフィルタを適用してみます。これはActionScriptになります。</p>
<pre class="prettyprint">
package {
    import flash.display.*;
    import flash.filters.*;

    public class filter_test extends Sprite
    {
        [Embed(source="test.pbj", mimeType="application/octet-stream")]
        private static var ShaderByteCode:Class;

        [Embed(source="dummy.jpg")]
        private static var Image1:Class;

        private var bmp1:Bitmap;

        public function filter_test()
        {
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;

            bmp1 = new Image1() as Bitmap;
            addChild(bmp1);

            var shader:Shader = new Shader(new ShaderByteCode());
            bmp1.filters = [new ShaderFilter(shader)];
        }
    }
}
</pre>
<div class="clearfix">
<div class="shadow"><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="Screen" width="200" height="200" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/wp-content/uploads/2009/03/filter_test.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><param name="allowScriptAccess" value="sameDomain" /><embed src="/wp-content/uploads/2009/03/filter_test.swf" quality="high" bgcolor="#ffffff" width="200" height="200" name="Screen" align="middle" play="true" loop="false" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></div>
<p>実行すると、左のようになります。これは実際作成したswfファイルになっています。</p>
<p>最初の生成画像と全く同じになっていることが分かります。
</p></div>
<h3>blendShaderにすると・・・</h3>
<p>次に、2枚の画像に対してブレンドモードでShaderを適用してみます。フィルタも若干（といっても入力を増やすだけですが）変更します。</p>
<pre class="prettyprint">
&lt;languageVersion : 1.0;&gt;

kernel SampleFilter
&lt;   namespace : "jp.flup";
    vendor : "Flup Inc.";
    version : 1;
    description : "outCoord test filter";
&gt;
{
    input image4 src;
    input image4 src2;
    output pixel4 dst;

    void
    evaluatePixel()
    {
        dst.r = (outCoord().x-100.0)/200.0;
        dst.g = (100.0-outCoord().y)/200.0;
        dst.b = 0.0;
        dst.a = 1.0;
    }
}
</pre>
<p>このようにして、入力画像を2つ使うことができるようにします（実際使ってはいませんが・・）。</p>
<p>次に、ActionScript側も入力画像を2つ使ってblendShaderを指定するように変更します。</p>
<pre class="prettyprint">
package {
    import flash.display.*;
    import flash.filters.*;

    public class filter_test extends Sprite
    {
        [Embed(source="test.pbj", mimeType="application/octet-stream")]
        private static var ShaderByteCode:Class;

        [Embed(source="dummy.jpg")]
        private static var Image1:Class;

        private var bmp1:Bitmap;
        private var bmp2:Bitmap;

        public function filter_test()
        {
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;

            bmp1 = new Image1() as Bitmap;
            addChild(bmp1);

            bmp2 = new Image1() as Bitmap;
            addChild(bmp2);

            var shader:Shader = new Shader(new ShaderByteCode());
            bmp2.blendMode = BlendMode.SHADER;
            bmp2.blendShader = shader;
        }
    }
}
</pre>
<p>実際には入力画像はつかっておらず、outCoord()の値のみで出力画像を生成しているので、結果は以前と変わらないはずですが・・・。</p>
<div class="clearfix">
<div class="shadow"><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="Screen" width="200" height="200" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/wp-content/uploads/2009/03/filter_test2.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><param name="allowScriptAccess" value="sameDomain" /><embed src="/wp-content/uploads/2009/03/filter_test2.swf" quality="high" bgcolor="#ffffff" width="200" height="200" name="Screen" align="middle" play="true" loop="false"  allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></div>
<p>このように、緑色のベタ塗りになってしまいました・・・。最初の画像と異なっているのは一目瞭然ですね。
</p></div>
<h3>どういうことなのか？</h3>
<p>これが仕様なのかバグなのかは私には分かりませんし、私の方法が悪いのかもしれませんが、blendShaderでpbjを使うと、outCoord()が出力ピクセル毎に（ほぼ）同じ値になってしまうようです。ほぼ、と書いたのは全く同じかどうか確認することができず、座標系が異なっている可能性もあるので・・。</p>
<p>ただ、Pixel Benderでは1ピクセルにつき座標を1増減するつもりで記述している（し、Pixel Bender Toolkitではそれで問題なく動作を確認している）ので、outCoord()の値によってピクセル値を制御することをblendShaderでやりたい場合は今回のような問題が発生しそうです。</p>
<p>一体これはどういうことなんでしょうね？どなたか原因が分かる方いらっしゃったらお教えください・・・。</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/flipflup?a=ElmY6sFMZXM:_l9RjI2lEbQ:OAQBO0PjnPA"><img src="http://feeds.feedburner.com/~ff/flipflup?d=OAQBO0PjnPA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.flup.jp/2009/03/14/pixel-bender_with_blendshader/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.flup.jp/2009/03/14/pixel-bender_with_blendshader/</feedburner:origLink></item>
		<item>
		<title>RubyでOpenGLをやってみる</title>
		<link>http://feedproxy.google.com/~r/flipflup/~3/-NsnSovjulU/</link>
		<comments>http://blog.flup.jp/2009/03/12/programming_ruby_openg/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 06:17:27 +0000</pubDate>
		<dc:creator>flipper</dc:creator>
		
		<category><![CDATA[3D]]></category>

		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.flup.jp/?p=334</guid>
		<description><![CDATA[

昨日、広島Ruby会議 01-2009 に行ってきました。
なかなか盛況でたくさんの方が参加されていましたが、スーツ率が高く若干肩身が狭かったです（笑）
実は私は今までRubyは触ったことがまったくなかったのですが今 [...]]]></description>
			<content:encoded><![CDATA[<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/ruby.png" alt="ruby" title="ruby" width="128" height="128" class="alignnone size-full wp-image-335" /></div>
<p>昨日、広島Ruby会議 01-2009 に行ってきました。</p>
<p>なかなか盛況でたくさんの方が参加されていましたが、スーツ率が高く若干肩身が狭かったです（笑）</p>
<p>実は私は今までRubyは触ったことがまったくなかったのですが今回イベントに参加してみて、興味が出てきたのでちょっとやってみようかと思います。
</p></div>
<p>お題としては、最近久々にいろいろやっている3D系のプログラムを書いてみることにします。果たしてうまくいくのかどうか・・・。<br />
<span id="more-334"></span></p>
<h3>環境準備</h3>
<p>開発環境はUbuntu 8.10で、rubyパッケージはインストール済みの状態でした。</p>
<p>RubyでOpenGLをやる場合、ruby-opengl というgems（Rubyのライブラリパッケージ管理のシステム）のパッケージが必要なようなので、入れてみます。</p>
<div class="terminal">
<ul>
<li class="root">gem install ruby-opengl</li>
</ul>
</div>
<p>すると、gemコマンドがないと怒られました・・・。rubygemsパッケージが入っていなかったようなので、synapticからインストールします（パッケージ名が分からなかったので。apt-get install rubygems でもOK）。</p>
<p>再度、先ほどのコマンドを実行すると、今度は rake コマンドがないといわれたので、</p>
<div class="terminal">
<ul>
<li class="root">apt-get install rake</li>
</ul>
</div>
<p>します。</p>
<p>今度こそいけるかと思いきや、大量のコンパイルエラーが・・・。エラーを追ってみてみると、どうやらOpenGLのGLUT関係のヘッダのincludeでこけている模様。</p>
<p>再びsynapticからパッケージをopenglとかで検索してみてみると、freeglut3-devというのを発見！たぶんこれだろうということで、インストール。</p>
<p>ここで、最初に入れたruby-openglのインストールコマンドを実行すると、ようやくインストールに成功しました。</p>
<h3>あとはOpenGLのコードを書くだけ</h3>
<p>実際大変だったのは、上記の環境の設定で、あとは公式サイトのリファレンスを見たりしましたがそれほど難しいところはありませんでした。</p>
<p>作法(?)として、セミコロンがいらなかったり、クラスやメソッドの宣言で { } を使わなかったり、インスタンス変数に@を付けたり、インスタンス化が、new Class() ではなく、Class.new() にするといったところは多少戸惑いましたが、覚えれば何てことはなさそうです。</p>
<p>今回作ったコードは以下のような感じです。</p>
<pre class="prettyprint">
#!/usr/bin/ruby

#-----------------------------------------
# GLUTでティーポットを描画するだけのプログラム
# @author flipper
# @date   2009.03.12
#-----------------------------------------

require "rubygems"
require "opengl"
require "glut"

class Teapot
    LIGHT_POSITION = [0.25, 1.0, 0.25, 0.0]
    LIGHT_DIFFUSE  = [1.0, 1.0, 1.0]
    LIGHT_AMBIENT  = [0.25, 0.25, 0.25]
    LIGHT_SPECULAR = [1.0, 1.0, 1.0]

    MAT_DIFFUSE   = [1.0, 0.0, 0.0]
    MAT_AMBIENT   = [0.25, 0.25, 0.25]
    MAT_SPECULAR  = [1.0, 1.0, 1.0]
    MAT_SHININESS = [32.0]

    def reshape(w,h)
        GL.Viewport(0,0,w,h)

        GL.MatrixMode(GL::GL_PROJECTION)
        GL.LoadIdentity()
        GLU.Perspective(45.0, w.to_f()/h.to_f(), 0.1, 100.0)
    end

    def display()
        GL.MatrixMode(GL::GL_MODELVIEW)
        GL.LoadIdentity()
        GLU.LookAt(0.5, 1.5, 2.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)

        GL.Lightfv(GL::GL_LIGHT0, GL::GL_POSITION, LIGHT_POSITION)
        GL.Lightfv(GL::GL_LIGHT0, GL::GL_DIFFUSE, LIGHT_DIFFUSE)
        GL.Lightfv(GL::GL_LIGHT0, GL::GL_AMBIENT, LIGHT_AMBIENT)
        GL.Lightfv(GL::GL_LIGHT0, GL::GL_SPECULAR, LIGHT_SPECULAR)

        GL.Materialfv(GL::GL_FRONT, GL::GL_DIFFUSE, MAT_DIFFUSE)
        GL.Materialfv(GL::GL_FRONT, GL::GL_AMBIENT, MAT_AMBIENT)
        GL.Materialfv(GL::GL_FRONT, GL::GL_SPECULAR, MAT_SPECULAR)
        GL.Materialfv(GL::GL_FRONT, GL::GL_SHININESS, MAT_SHININESS)

        GL.ClearColor(0.0, 0.0, 0.0, 1.0)
        GL.Clear(GL::GL_COLOR_BUFFER_BIT | GL::GL_DEPTH_BUFFER_BIT)

        GL.Rotate(@rotX, 1, 0, 0)
        GL.Rotate(@rotY, 0, 1, 0)
        GLUT.SolidTeapot(0.5)

        GLUT.SwapBuffers()
    end

    def mouse(button,state,x,y)
        if button == GLUT::GLUT_LEFT_BUTTON &#038;&#038; state == GLUT::GLUT_DOWN then
            @start_x = x
            @start_y = y
            @drag_flg = true
        elsif state == GLUT::GLUT_UP then
            @drag_flg = false
        end
    end

    def motion(x,y)
        if @drag_flg then
            dx = x - @start_x
            dy = y - @start_y

            @rotY += dx
            @rotY = @rotY % 360

            @rotX += dy
            @rotX = @rotX % 360
        end
        @start_x = x
        @start_y = y
        GLUT.PostRedisplay()
    end

    def initialize()
        @start_x = 0
        @start_y = 0
        @rotY = 0
        @rotX = 0
        @drag_flg = false
        GLUT.InitWindowPosition(100, 100)
        GLUT.InitWindowSize(300,300)
        GLUT.Init
        GLUT.InitDisplayMode(GLUT::GLUT_DOUBLE | GLUT::GLUT_RGB | GLUT::GLUT_DEPTH)
        GLUT.CreateWindow("Ruby de OpenGL")

        GL.Enable(GL::GL_DEPTH_TEST)
        GL.Enable(GL::GL_LIGHTING)
        GL.Enable(GL::GL_LIGHT0)

        GL.FrontFace(GL::GL_CW)
        GL.Enable(GL::GL_AUTO_NORMAL)
        GL.Enable(GL::GL_NORMALIZE)
        GL.Enable(GL::GL_DEPTH_TEST)
        GL.DepthFunc(GL::GL_LESS)

        GL.ShadeModel(GL::SMOOTH)

        GLUT.ReshapeFunc(method(:reshape).to_proc())
        GLUT.DisplayFunc(method(:display).to_proc())
        GLUT.MouseFunc(method(:mouse).to_proc())
        GLUT.MotionFunc(method(:motion).to_proc())
    end

    def start()
        GLUT.MainLoop()
    end
end

Teapot.new().start()
</pre>
<p><a class="attached" href='http://blog.flup.jp/wp-content/uploads/2009/03/rubygl.rb'>rubygl.rb</a></p>
<p>保存後、以下のコマンドで実行できます。</p>
<div class="terminal">
<ul>
<li>ruby rubygl.rb</li>
</ul>
</div>
<p><img src="http://blog.flup.jp/wp-content/uploads/2009/03/ruby-opengl.png" alt="ruby-opengl" title="ruby-opengl" width="302" height="329" class="alignnone size-full wp-image-342" /></p>
<p>マウスのドラッグで回転ができます（が、適当につくっているので軸がx,y軸固定です・・）。</p>
<p>今回のコードはRubyのコードというよりは単にOpenGLのコードになってしまったような気もするので、今度はWebアプリっぽいものを作ってみたいと思います。</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/flipflup?a=-NsnSovjulU:9kRfDYuFPmk:OAQBO0PjnPA"><img src="http://feeds.feedburner.com/~ff/flipflup?d=OAQBO0PjnPA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.flup.jp/2009/03/12/programming_ruby_openg/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.flup.jp/2009/03/12/programming_ruby_openg/</feedburner:origLink></item>
		<item>
		<title>Flex BuilderのFP10対応方法</title>
		<link>http://feedproxy.google.com/~r/flipflup/~3/-lPNfSoCgAo/</link>
		<comments>http://blog.flup.jp/2009/03/06/fx3_fp10/#comments</comments>
		<pubDate>Fri, 06 Mar 2009 10:21:55 +0000</pubDate>
		<dc:creator>flipper</dc:creator>
		
		<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://blog.flup.jp/?p=315</guid>
		<description><![CDATA[

昨年秋に正式公開されたFlash Player 10ですが、かなりいろいろな機能が強化されているようで、中でも3D機能のネイティブ対応は大きいのではないかと思います。

そこで、Flex Builderで10対応の新 [...]]]></description>
			<content:encoded><![CDATA[<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/fx3_fp10.jpg" alt="fx3_fp10" title="fx3_fp10" width="240" height="180" class="alignnone size-full wp-image-316" /></div>
<p>昨年秋に正式公開された<a href="http://www.adobe.com/jp/products/flashplayer/">Flash Player 10</a>ですが、かなりいろいろな機能が強化されているようで、中でも3D機能のネイティブ対応は大きいのではないかと思います。</p>
</div>
<p>そこで、Flex Builderで10対応の新機能を使ってみようと思ったのですが、そのままではうまくいかないようです。色々試して出来たのでやり方を紹介します。<br />
<span id="more-315"></span></p>
<h3>最新のFlex SDKをダウンロード</h3>
<p>まず、元から入っているSDKは古いのでAdobeのサイトから最新のSDKをダウンロードします。(<a href="http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+3">Download Flex 3</a>) Adobe SDKとオープンソースSDKがありますが、これは自分が開発するライセンスをオープンソースにしたい場合はオープンソースSDKの方を選べばOKです（Adobe SDKの方はクローズドソースのパッケージが含まれているそうです）。</p>
<p>ダウンロードしたら、Flex Builderのインストール先の中の sdks ディレクトリの中へフォルダを作って解凍します。</p>
<h3>flex-config.xmlの書き換え</h3>
<p>解凍後、SDKの中にframeworksというディレクトリがありますのでそれを開きます。</p>
<p>その中の、flex-config.xmlのうち、以下の記述を変更します。</p>
<pre class="prettyprint">
    &lt;target-player&gt;9.0.124&lt;/target-player&gt;
　　　　　↓
    &lt;target-player&gt;10.0.0&lt;/target-player&gt;
</pre>
<pre class="prettyprint">
      &lt;external-library-path&gt;
          &lt;path-element&gt;libs/player/{targetPlayerMajorVersion}/playerglobal.swc&lt;/path-element&gt;
      &lt;/external-library-path&gt;
　　　　　↓
      &lt;external-library-path&gt;
          &lt;path-element&gt;libs/player/10/playerglobal.swc&lt;/path-element&gt;
      &lt;/external-library-path&gt;
</pre>
<pre class="prettyprint">
      &lt;library-path&gt;
         &lt;path-element&gt;libs&lt;/path-element&gt;
		 &lt;!-- keep the original location in the libpath for backwards-compatibility --&gt;
         &lt;path-element&gt;libs/player&lt;/path-element&gt;
         &lt;path-element&gt;libs/player/{targetPlayerMajorVersion}&lt;/path-element&gt;
	     &lt;path-element&gt;locale/{locale}&lt;/path-element&gt;
      &lt;/library-path&gt;
　　　　　↓
      &lt;library-path&gt;
         &lt;path-element&gt;libs&lt;/path-element&gt;
		 &lt;!-- keep the original location in the libpath for backwards-compatibility --&gt;
         &lt;path-element&gt;libs/player&lt;/path-element&gt;
         &lt;path-element&gt;libs/player/10&lt;/path-element&gt;
	     &lt;path-element&gt;locale/{locale}&lt;/path-element&gt;
      &lt;/library-path&gt;
</pre>
<h3>Flex Builderの設定</h3>
<p>[ウィンドウ]→[設定]で、設定画面を開き、左側のFlex > インストールされている Flex SDKを選びます。<br />
するとSDKの一覧が出るので、「追加」ボタンで最初に解凍したSDKのパスを指定します。</p>
<p>すると一覧に追加されるので、新しく追加されたSDKの左にチェックを入れてOKボタンを押します。</p>
<p>次に、新しいプロジェクトを作り、プロジェクトのプロパティを表示します。この中のFlexビルドパスに、playerglobal.swcというのがあるのですが、これは9用のものなので削除します。そして、SWCの追加をクリックしてSDK_ROOT/frameworks/libs/player/10/playerglobal.swcを追加します。</p>
<p>追加したplayerglobal.swcの左の三角をクリックして、リンクタイプを編集し、「外部」に設定しておきます。</p>
<p>最後に、プロジェクトプロパティの中の必要なFlash Playerバージョンを 10.0.0 にすればOKです。</p>
<h3>テスト</h3>
<p>実際にPlayer10のコードが作れるかどうか確かめてみます。以下のソースをビルドして実行できるかどうか見てみてください。<br />
<a href='http://blog.flup.jp/wp-content/uploads/2009/03/fp10_test.zip' class="attached">fp10_test.zip</a><br />
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="Screen" width="200" height="200" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/wp-content/uploads/2009/03/fp10_test.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><param name="allowScriptAccess" value="sameDomain" /><param name="wmode" value="gpu" /><embed src="/wp-content/uploads/2009/03/fp10_test.swf" quality="high" bgcolor="#ffffff" width="200" height="200" name="Screen" align="middle" play="true" loop="false" wmode="gpu"  allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/flipflup?a=-lPNfSoCgAo:HRnEyOuNyno:OAQBO0PjnPA"><img src="http://feeds.feedburner.com/~ff/flipflup?d=OAQBO0PjnPA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.flup.jp/2009/03/06/fx3_fp10/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.flup.jp/2009/03/06/fx3_fp10/</feedburner:origLink></item>
		<item>
		<title>Pixel Benderでバンプマッピング</title>
		<link>http://feedproxy.google.com/~r/flipflup/~3/jMhcjP_rdyI/</link>
		<comments>http://blog.flup.jp/2009/03/06/bump_mapping_using_pixel_bender/#comments</comments>
		<pubDate>Fri, 06 Mar 2009 07:28:22 +0000</pubDate>
		<dc:creator>flipper</dc:creator>
		
		<category><![CDATA[3D]]></category>

		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.flup.jp/?p=291</guid>
		<description><![CDATA[

Pixel Benderというのは、Adobeが開発中の画像・動画処理の仕組みで、出力画像をピクセル毎にプログラマブルに生成することができるようにするものです。
また、GPUのハードウェア支援も得ることができるので、 [...]]]></description>
			<content:encoded><![CDATA[<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/pixel_bender.jpg" alt="pixel_bender" title="pixel_bender" width="240" height="180" class="alignnone size-full wp-image-292" /></div>
<p><a href="http://labs.adobe.com/technologies/pixelbender/">Pixel Bender</a>というのは、Adobeが開発中の画像・動画処理の仕組みで、出力画像をピクセル毎にプログラマブルに生成することができるようにするものです。</p>
<p>また、GPUのハードウェア支援も得ることができるので、処理によってはかなりの高速化が期待できます。
</p></div>
<p>現段階では、Adobe After Effects CS4とFlash Player 10、Photoshop CS4 に対応しているようです。実際の開発では pbk (Pixel Bender Kernel File) という形式のコードを作成していくのですが、これは基本的にどのアプリケーションでも同じコードで動作するとのことです（実際にはAfter EffectsやFlashは細かい制限がありますので、すべてがそのままで動作するわけではないです）。</p>
<p>今回は実験がてら、法線マップを使ったバンプマッピングをPixel Benderでやってみます。<br />
<span id="more-291"></span></p>
<h3>3D基礎知識</h3>
<p>いきなり、「法線マップ」と言われても訳が分からないと思いますので、簡単に3Dの基礎的な部分を書いておきます。</p>
<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/coord.jpg" alt="coord" title="coord" width="240" height="180" class="alignnone size-full wp-image-296" /></div>
<p>まず、3次元の座標系についてですが、今回は左右をx軸で右が正、上下をy軸で上が正、奥行きをz軸で手前が正というようにします（左図参照）。
</p></div>
<p>次に、法線というのは3D空間において、面あるいは点がどの方向を向いているかを表すベクトルのことです。2次元に置き換えて考えると、常にこちらを向いていることになるので、(0, 0, 1) となります（ベクトルの成分表記で）。</p>
<p>この法線というものは光源に対してその場所がどういう色になるか計算するのに使われます。これをシェーディングといいます。今回はこのシェーディングの計算のうち、ランバートとフォンのモデルを使います。</p>
<h3>ランバート反射</h3>
<p>あまり反射率が高くない（ぴかぴかしていない）材質の色というのは視点の位置にあまり左右されず同じ色に見えます。これを拡散反射(diffuse reflection)といい、代表的な反射計算のモデルとして<a href="http://ja.wikipedia.org/wiki/%E3%83%A9%E3%83%B3%E3%83%90%E3%83%BC%E3%83%88%E5%8F%8D%E5%B0%84">ランバート反射</a>というものがあります。</p>
<p>面に対して垂直に光をあてる時がもっとも明るくなることから考えられており、法線ベクトルと光線ベクトルの逆ベクトルの内積（ともに正規化された状態で）から算出できます。</p>
<h3>鏡面反射</h3>
<p>一方、ぴかぴかした反射は鏡を考えれば明らかなように、視点の位置によって見え方が変わります。これを鏡面反射といいます(specular reflection)。この近似についてもさまざまなシミュレーションモデルが考案されているのですが、有名なものに<a href="http://ja.wikipedia.org/wiki/Phong%E3%81%AE%E5%8F%8D%E5%B0%84%E3%83%A2%E3%83%87%E3%83%AB">フォンのモデル</a>があります。</p>
<p>このフォンのモデルの考え方は、視線の反射ベクトルと光線ベクトルの角度が小さければ小さいほど明るくなり、その角度が大きいほど暗くなるというもので、要は光が反射する先にいればまぶしく感じるけど、そこからずれるほどまぶしさを感じなくなるということから考えられています。</p>
<p>しかし、反射ベクトルを計算するのは大変な場合もあるので、それを簡略化して光線ベクトルと視線ベクトルの中間のハーフベクトルを使う方法が考えられました。これがBlinnによる修正モデルです。</p>
<p>元のフォンのモデルは反射ベクトルと光線ベクトルの内積のべき乗で算出しますが、Blinn-Phong修正モデルではハーフベクトルと法線ベクトルの内積のべき乗を使います。なぜこうなるかは、反射ベクトルと光線ベクトルが一致するとき、ハーフベクトルと法線ベクトルが一致する関係にあることから分かると思います。</p>
<h3>法線マップ</h3>
<div class="clearfix">
<div class="shadow"><a rel="lightbox[normal_map]" href="http://blog.flup.jp/wp-content/uploads/2009/03/stonewallnormal_mini.png"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/stonewallnormal_mini-150x150.png" alt="stonewallnormal_mini" title="stonewallnormal_mini" width="150" height="150" class="alignnone size-thumbnail wp-image-302" /></a></div>
<p>法線マップというのは、前述の法線データをピクセルごとに画像に保存したものです。ベクトルというのは正規化すると各座標の成分が-1〜1の範囲におさまるので、それを0〜255の範囲に置き換えてx=>r, y=>g, z=>bにそれぞれ保存できます。
</p></div>
<p>3Dのプログラムでは、このように画像にベクトルデータをマッピングしておくことがよくあります。複雑な照明計算を前もって行っておき、それを保存した画像を使ってレンダリング時の計算を減らすことができます。</p>
<h3>Pixel Benderでコーディング</h3>
<p>今回のプログラムは点光源（場所によって光線ベクトルが異なる。どの場所でも光線ベクトルが同じ光源は平行光源という）として扱い、光源との距離によって明るさが減衰するようにしてみました。減衰のモデルは A = 1 / (a + D * b + D * D * c) （Dは光源との距離、a,b,cは定数）として、計算結果にAを乗算しています。</p>
<p>実際のコードは以下のようになります。</p>
<pre class="prettyprint">
&lt;languageVersion : 1.0;&gt;

kernel BumpFilter
&lt;   namespace : "jp.flup";
    vendor : "Flup Inc.";
    version : 1;
    description : "Bump mapping filter";
&gt;
{
    // 500x500限定にしている。parameterにして設定可能にしてもいい
    const float2 textureSize = float2(500.0, 500.0);
    // 平面の位置となるZ座標（何でも良いけど光源の位置とかと関係してくるので、相対的に調整が必要）
    const float textureZ = -1000.0;

    // 光源の位置
    parameter float3 lightPos
    &lt;
        minValue: float3(-textureSize.x/2.0,-textureSize.y/2.0,textureZ + 10.0);
        maxValue: float3(textureSize.x/2.0,textureSize.y/2.0,textureZ + 100.0);
        defaultValue: float3(0.0, 0.0,textureZ + 20.0);
    &gt;;
    // 視点の位置（原点固定）
    const float3 viewPos = float3(0.0, 0.0, 0.0);

    // specular計算でのべき乗（大きいほど反射範囲が収束します）
    parameter float power
    &lt;
        minValue: 0.0;
        maxValue: 1000.0;
        defaultValue: 30.0;
    &gt;;

    // 減衰定数 A = 1 / (x + D * y + D * D * z)
    parameter float3 attenuate
    &lt;
        minValue: float3(0,0,0);
        maxValue: float3(1.0,1.0,0.04);
        defaultValue: float3(0.2,0.1,0.001); // z は距離の2乗に乗算するので小さくしています
    &gt;;

    // 拡散光の強度（大きいほど素材の色が見えます）
    parameter float diffuseIntensity
    &lt;
        minValue: 1.0;
        maxValue: 100.0;
        defaultValue: 20.0;
    &gt;;

    // Image1 : diffuse texture
    input image4 colorTex;
    // Image2 : normal texture
    input image4 normalTex;

    output pixel4 dst;

    void
    evaluatePixel()
    {
        // 現在計算中の座標
        float3 pos = float3(outCoord().x-textureSize.x/2.0,textureSize.y/2.0-outCoord().y,textureZ);
        // 光線ベクトル（光源から物体へのベクトル）
        float3 lightVector = pos-lightPos;
        // 光源と物体の距離（ベクトル長で求まる）
        float lightDistance = length(lightVector);
        // 減衰率の計算
        float attenuator = attenuate.x + lightDistance * attenuate.y + lightDistance * lightDistance * attenuate.z;
        if(attenuator == 0.0)
            attenuator = 1.0;  // ゼロ除算防止

        float3 light = normalize(lightVector);

        // 視線ベクトル（視点から物体へのベクトル）
        float3 viewVector = pos-viewPos;
        float3 view = normalize(viewVector);

        // diffuse色の取得
        pixel4 inputColor = sampleNearest(colorTex,outCoord());

        // 法線ベクトルの取得
        float3 normal = normalize(float3(sampleLinear(normalTex, outCoord()).rgb * 2.0 - 1.0));
        if(normal.z &lt; 0.0)
            normal.z = -normal.z; // 座標系の違いでZ値が負になっているときは符号を反転

        // ハーフベクトル = 光線の逆ベクトル + 視線の逆ベクトル
        float3 halfVector = normalize(-light -view);
        // specular成分の計算
        float dp = dot(normal, halfVector);
        float specular = pow(max(dp, 0.0), power);
        // diffuseとspecularを加算してclamp
        dst.rgb = clamp((inputColor.rgb * dot(normal, -light) * diffuseIntensity + float3(1.0,1.0,1.0) * specular)/attenuator, 0.0, 1.0);
    }
}
</pre>
<p>実行すると、以下のような感じになります。</p>
<div class="clearfix">
<a href="http://blog.flup.jp/wp-content/uploads/2009/03/pixel_bender_capture.jpg"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/pixel_bender_capture-300x251.jpg" alt="pixel_bender_capture" title="pixel_bender_capture" width="300" height="251" class="alignnone size-medium wp-image-309" /></a></div>
<p>今回のコードは以下からダウンロードできます。<br />
<a class="attached" href='http://blog.flup.jp/wp-content/uploads/2009/03/pixel_bender_bump_mapping.zip'>pixel_bender_bump_mapping.zip</a></p>
<p>次は、このPixel BenderのコードをFlexで使ってみたいと思います。</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/flipflup?a=jMhcjP_rdyI:fTaz8Zuh0kY:OAQBO0PjnPA"><img src="http://feeds.feedburner.com/~ff/flipflup?d=OAQBO0PjnPA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.flup.jp/2009/03/06/bump_mapping_using_pixel_bender/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.flup.jp/2009/03/06/bump_mapping_using_pixel_bender/</feedburner:origLink></item>
		<item>
		<title>dragdropuploadの日本語ファイル名対応</title>
		<link>http://feedproxy.google.com/~r/flipflup/~3/yJQs2mZeu24/</link>
		<comments>http://blog.flup.jp/2009/03/02/dragdropupload_modified_for_japanese_filename/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 10:39:52 +0000</pubDate>
		<dc:creator>flipper</dc:creator>
		
		<category><![CDATA[一般]]></category>

		<guid isPermaLink="false">http://blog.flup.jp/?p=278</guid>
		<description><![CDATA[

dragdropuploadという便利なFirefoxの拡張があります。定番の拡張なのでご存知の方も多いことと思います。
簡単に説明すると、この拡張をインストールするとエクスプローラなどからファイルアップロードのフォ [...]]]></description>
			<content:encoded><![CDATA[<div class="clearfix">
<div class="shadow"><img src="http://blog.flup.jp/wp-content/uploads/2009/03/capture.png" alt="ファイルアップロード" title="ファイルアップロード" width="220" height="165" class="alignnone size-full wp-image-279" /></div>
<p><a href="https://addons.mozilla.org/ja/firefox/addon/2190">dragdropupload</a>という便利なFirefoxの拡張があります。定番の拡張なのでご存知の方も多いことと思います。</p>
<p>簡単に説明すると、この拡張をインストールするとエクスプローラなどからファイルアップロードのフォームへドラッグ＆ドロップでファイルの指定ができるというものです。
</p></div>
<p>しかし、Linuxだからなのか分かりませんが日本語ファイル名をGmailの添付に指定しようとするとURIエンコードされた状態になってしまい、正常にアップロードできません。</p>
<p>いろいろとGoogleで検索をかけてみたものの、<a href="http://xxsionxx.blog17.fc2.com/blog-entry-1125.html">サイドバーを日本語化したもの</a>を配布しているところは見つかりましたが今回の現象とは違うので解決には至りませんでした。</p>
<p>そこで、今回自力で修正してみることにしました。<br />
<span id="more-278"></span></p>
<h3>xpiの中身</h3>
<p>xpi ファイルは実はzip形式のファイルになっているのでまずは書庫を解凍してみます（実際にはnautilusでダブルクリックするとFile Rollerで書庫内閲覧ができるので、そちらから処理しました）。</p>
<p>xpiの中には以下のようなファイルが入っています。</p>
<ul>
<li>chrome</li>
<ul>
<li>dragdropupload.jar</li>
</ul>
<li>install.rdf</li>
<li>LICENSE.txt</li>
</ul>
<h3>寄り道Tips</h3>
<p>今回はまったく関係ないのですが、install.rdfはインストールに必要となる情報が定義されています。</p>
<p>たとえば、古いバージョンの拡張でFirefoxをアップデートしたときに対応されなくなった、という状況がよくあります。そんなとき、（保証はもちろんないですが）このファイルを書き換えることで強制的にインストールすることができます。</p>
<pre class="prettyprint">
        &lt;em:targetApplication>&gt;
            &lt;Description>&gt;
                &lt;em:id&gt;{ec8030f7-c20a-464f-9b0e-13a3a9e97384}&lt;/em:id>&gt;
                    &lt;em:minVersion&gt;1.0&lt;/em:minVersion&gt;
                    &lt;em:maxVersion&gt;3.0.*&lt;/em:maxVersion&gt;
            &lt;/Description&gt;
        &lt;/em:targetApplication&gt;
</pre>
<p>このファイルの上記の箇所がFirefoxでの対応バージョンの定義となっていますので、maxVersionを3.1.*とすれば、Firefox 3.1にアップデートされた場合でもインストールすることができます。</p>
<p>繰り返しますが、この操作は配布元が確認できていない状態でのインストールなのであくまでも自己責任で。</p>
<h3>jsファイルの修正</h3>
<p>さて、脇道にそれましたが、ファイル名をセットしているのはdragdropupload.jarというファイル内のjsファイルとなります（.jarファイルも.xpi同様、zip形式になっています）。</p>
<p>今回修正するのは書庫内の content/dragdropupload.js です。</p>
<p>ドロップイベントに関連付けられたハンドラを修正すべき、ということから dragDropHandler あたりを見てみます。その中に、onDrop 関数を発見！！ここでドロップ時の処理を行っているに違いありません。</p>
<p>中を見ると、contentType に応じて処理が分岐されています。nautilusからドロップしたときのcontentTypeがどれか分からなかったので、とりあえず alert(td.flavour.contentType) を追加して拡張をインストールしてみると、&#8221;application/x-moz-file&#8221; と出てきたのでその部分を修正することにしました。</p>
<p>この中でファイル名をセットしているところでURIデコードすればよさそうです。JavaScriptでのURIデコードは decodeURIComponent() 関数で行うことができるので、それを以下のように追加します。</p>
<pre class="prettyprint">
        case "text/x-moz-url":
        case "application/x-moz-file":
            {
                // check if there are multiple files ...
                if(multi)
                {
                    // assume all of flavour moz-file
                    var files = [];
                    for(var i = 0; i < transferData.dataList.length; i++)
                    {
                        var td = transferData.dataList[i];

                        for(var j = 0; j < td.dataList.length; j++)
                        {
                            var fd = td.dataList[j];
                            if(fd.flavour.contentType == "application/x-moz-file")
                            {
                                files.push(decodeURIComponent(fd.data.path)); // ここを変更
                           }
                        }
                    }
                    this.applyFiles(evt, files);
                }
            }
            break;
</pre>
<p>一応、これでnautilusからGmailの添付へドラッグ＆ドロップできるようになりました。なお、変更を反映してインストールするにはzip圧縮して元のファイル名に戻せばOKです。</p>
<p><span class="notice">※他のツールからのドロップや他のOSについては考慮していません</span></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/flipflup?a=yJQs2mZeu24:MPe0sAFfDUI:OAQBO0PjnPA"><img src="http://feeds.feedburner.com/~ff/flipflup?d=OAQBO0PjnPA" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.flup.jp/2009/03/02/dragdropupload_modified_for_japanese_filename/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.flup.jp/2009/03/02/dragdropupload_modified_for_japanese_filename/</feedburner:origLink></item>
	</channel>
</rss>
