<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.jp/~d/styles/atom10japanesefull.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.jp/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom">
   <title>NUTSU</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/" />
   
   <id>tag:nutsu.com,2008:/blog//1</id>
   <updated>2008-11-20T08:46:50Z</updated>
   
   <generator uri="http://www.sixapart.com/movabletype/">Movable Type 3.35</generator>

<link rel="self" href="http://feeds.feedburner.jp/nutsu" type="application/atom+xml" /><entry>
   <title>[as]Alchemyためしてみる</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/112017_alchemy_test.html" />
   <id>tag:nutsu.com,2008:/blog//1.99</id>
   
   <published>2008-11-20T08:40:50Z</published>
   <updated>2008-11-20T08:46:50Z</updated>
   
   <summary> 先日Adobeから発表された、C/C++のコードをActionScriptで利...</summary>
   <author>
      <name />
      
   </author>
         <category term="ActionScript" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="6" label="actionscript" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="23" label="alchemy" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<p>
先日Adobeから発表された、C/C++のコードをActionScriptで利用できるという <a href="http://labs.adobe.com/technologies/alchemy/">Alchemy</a>。いろいろと情報が揃ってからぼちぼち触ってみようと思っていたけど、ついついちょっとだけってことで。<br/>
全然わからんことばかりなので、試しやすそうな疑似乱数 <a href="http://ja.wikipedia.org/wiki/メルセンヌ・ツイスタ" target="_blank">MersenneTwister</a> を錬金してみることにしました。
</p>

<p>
Alchemyを動かすには、<a href="http://labs.adobe.com/wiki/index.php/Alchemy:Documentation:Getting_Started">Adobe の Get Start</a> を見ればすんなりといった。amachangさんの<a href="http://d.hatena.ne.jp/amachang/20081118/1227005285">「C/C++ のコードを Flash Player で動かす！ Alchemy を速攻試してみる。」</a>も非常にわかりやすい。僕の場合は、Windows で Cygwin 環境でしたが同じような感じです。FlexSDK は <a href="http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+4">Gumbo</a> 使ってます。
</p>

<p>
Mersenne Twister については<a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/mt19937ar.html">「Mersenne Twister with improved initialization (2002)」</a> のソース(<a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c">mt19937ar.c</a>)を利用しています。<br/>
比較する為に用意したクラスは、<a href="http://onegame.bona.jp/tips/mersennetwister.html">Onegameさんの記事</a>を参考にさせていただきました。
</p>]]>
      <![CDATA[<p>
今回つくったコードとかはこちら。
</p>

<ul>
<li><a href="http://nutsu.com/blog-asset/srcs/mersenne.c">mersenne.c (Alchemy用Cソース)</a></li>
<li><a href="http://nutsu.com/blog-asset/srcs/mersenne.swc">mersenne.swc (AlchemyででけたSWC)</a></li>
<li><a href="http://nutsu.com/blog-asset/srcs/MersenneTwister.as">MersenneTwister.as (AS3版)</a></li>
<li><a href="http://nutsu.com/blog-asset/srcs/TestAlchemy.as">TestAlchemy.as (テスト用AS)</a></li>
</ul>


<h3 class="seq">とりあえず試す</h3>

<p>
今回は試してみようということで、mt19937ar.c の内、初期化の init_genrand 、乱数生成の genrand_int32 をラップしてASから使えるようにしてみる。<br/>
ラップの仕方などAlchemy的な部分は、AlchemyToolkit付属のサンプルや、<a href="http://labs.adobe.com/wiki/index.php/Alchemy:Documentation:Developing_with_Alchemy:C_API">ドキュメント</a> みながら見よう見まねで。
</p>

<p>
ここは適当ながら、gccしてみるとswcがでけた。
</p>

<pre>
gcc mersenne.c -swc -o mersenne.swc
</pre>

<p>
さっそくASで使ってみようと。
<p>

<pre>
mxmlc -library-path+=mersenne.swc --target-player=10.0.0 TestAlchemy.as
</pre>


<p>
で、for文で10万回とか回しながら genrand_int32() するテストをAS3版と比較してみる。が、Alchemy版がめっぽう遅い。フリーズしたんかと思った…。どうも呼び出しにはなかなかのコストがかかる模様。
</p>

<p>
この部分は、TestAlchemy.as の test_alchemy() のところ。mersenne.c では g_int32() です。
</p>




<h3 class="seq">C内でArrayつくったらどうか</h3>

<p>
乱数をひとつひとつ生成するのはあぎゃんな感じだったので、Cの方でActionScriptのArrayをつくったらパフォーマンスでるんでねーかと思ってテストしてみる。Alchemy的には、CでASのクラス生成、ASのメソッド呼び出しなところ。
</p>

<p>
TestAlchemy.as の test_alchemy_array() のところ。mersenne.c では g_int32_array() です。
</p>

<p>
結果は前と同じぐらい遅い…。CでASのメソッドを呼ぶのもコストかかってるかと…。ものによるんかも知れんけど。
</p>




<h3 class="seq">だったらでByteArrayならどうなの</h3>

<p>
ArrayがダメならByteArrayってことで、C内でByteArrayに乱数を詰め込んで返すことにしてみる。
</p>

<p>
TestAlchemy.as の test_alchemy_byteArray() のところ。mersenne.c では g_int32_byteArray() です。
</p>

<p>
結果は・・・・速くなった！何かうれしい。
</p>

<p>
<a href="http://nutsu.com/blog-asset/fp10/TestAlchemy.swf">TestAlchemyのSWFはこれ(FlashPlayer10必要です)</a>
</p>



<h3 class="seq">まとめっぽい何か</h3>

<p>
今回試してみた印象は、AS←→C 間のやりとりに想像以上にコストかかるらしいってこと。既存のCライブラリを移植していく場合、Cで実装する分、ASに移植する分の案配がパフォーマンスにもろ影響しそう。まだリリースはされてないので今後どうなるかわからんけども。ゆくゆくパフォーマンスのいい OpenCV が使えるようになるとうれしいなぁと。
</p>

]]>
   </content>
</entry>
<entry>
   <title>[f5]フラットぐらい…</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/103120_f5_lighttest.html" />
   <id>tag:nutsu.com,2008:/blog//1.98</id>
   
   <published>2008-10-31T11:39:33Z</published>
   <updated>2008-10-31T11:40:44Z</updated>
   
   <summary> フラットシェーディングぐらいできたらええんやろなぁ。と思いながらぼちぼちやって...</summary>
   <author>
      <name />
      
   </author>
         <category term="ActionScript" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="6" label="actionscript" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="17" label="frocessing" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<p>
フラットシェーディングぐらいできたらええんやろなぁ。と思いながらぼちぼちやってます。そんなんPV3DとかAway3Dとか使えば早いんですが…。まぁプラモ好きに完成品かえいうてるもんで。
</p>]]>
      <![CDATA[<p>
300個ぐらいのフラットシェーディングテスト。ミニマムな計算だけだけど中々重いなぁ。
</p>

<script type="text/javascript">
swfObject10("f5_light_test","/blog-asset/etu/f5_light_test.swf",425,550,"#000000");
</script>

<p>
簡易版なんで、DirectLightとPointLightぐらい実装すればよいかなぁ。関係ないけどシドミードのフラット好きです。
</p>

]]>
   </content>
</entry>
<entry>
   <title>[as]FP10をそろそろ。Matrix3Dとか</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/102321_matrix3d_test.html" />
   <id>tag:nutsu.com,2008:/blog//1.97</id>
   
   <published>2008-10-23T12:38:30Z</published>
   <updated>2008-10-23T12:41:59Z</updated>
   
   <summary> FlashPlayer10が公開されてしばらく、そろそろFP10向けの勉強を初...</summary>
   <author>
      <name />
      
   </author>
         <category term="ActionScript" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="6" label="actionscript" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="22" label="fp10" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<p>
FlashPlayer10が公開されてしばらく、そろそろFP10向けの勉強を初めてみようかと思ってます。とりあえずはGraphics辺りから始めようと思いますが、公開されたらテストしてみようと思ってたMatrix辺りから。<br/>
環境はなんとなく Flex4 Gumbo の Nightly Builds で（flashパッケージしか使わないけど）。
</p>

<p>
&gt;&gt; <a href="http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+4"  target="_blank">Flex4 Gumbo Downloads</a><br/>

&gt;&gt; <a href="http://download.macromedia.com/pub/labs/flashplayer10/flashplayer10_as3langref_070208.zip" target="_blank">flashplayer10 reference( 070208 )</a><br/>

&gt;&gt; <a href="http://livedocs.adobe.com/flex/gumbo/langref/" target="_blank">Gumbo Language Reference</a>
</p>]]>
      <![CDATA[<p>
最初に Matrix のパフォーマンスを見てみたのですが、ここは前と変わりがないようです。相変わらずちょと遅い。
</p>

<p>
で、Matrix3D の パフォーマンスを見たのですが、こちらは少し妙で。どうも遅い。テストは append, prepend系の行列計算を見たのですけど。テストデータが悪いのかもしれないと思える程、気持ち悪いぐらい遅い。遅いかと思ったら速いときもある…。微妙です。遅いときは自前で組んだものより50倍ぐらい遅い。謎です。遅くなる場合の条件がよくわからんのですが、気が向いたら調べるかもしれません。PV3D とか away3D の既存のライブラリは、そのまま自前の改良でいくんでしょうね。
</p>

<p>
とはいえ、Matrix3Dのメンバ関数を見ると、decompose()、recompose()、interpolate()、transformVectors()など、便利系、DisplayObjectとの整合性的なものが見られます。生っぽいMatrixのライブラリより利用するには便利なのかなぁという印象です。とりあえず簡単なサンプルをつくってみた。<br/>
※flashplayer10が必要です。
</p>

<script type="text/javascript">
swfObject10("TestMatrix3D","/blog-asset/TestMatrix3D.swf",425,425,"#000000");
</script>

<p>
ソースはこちら。
</p>

<pre>
package  
{
	import flash.events.Event;
	import flash.display.*;
	import flash.geom.*;
	
	[SWF(width=425, height=425, frameRate=60, backgroundColor=0x000000)]
	public class TestMatrix3D extends Sprite
	{
		private var particle_num:int = 3000;
		private var vertices_in:Vector.&lt;Number&gt;;
		private var vertices_out:Vector.&lt;Number&gt;;
		
		private var _matrix:Matrix3D;
		
		public function TestMatrix3D() 
		{
			//初期座標（x,y,z）と変換用のVectorつくる
			vertices_in  = new Vector.&lt;Number&gt;( particle_num*3, true );
			vertices_out = new Vector.&lt;Number&gt;( particle_num*3, true );
			
			//てきとうに座標いれとく
			for ( var i:int = 0; i &lt; particle_num ; i+=3 )
			{
				vertices_in[i]   = Math.random() * 200 - 100;  // x
				vertices_in[i+1] = Math.random() * 200 - 100;  // y 
				vertices_in[i+2] = Math.random() * 200 - 100;  // z
			}
			
			//今回はこれのテスト
			_matrix = new Matrix3D();
			
			//中心にしとくとか
			x = stage.stageWidth/2;
			y = stage.stageHeight/2;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			addEventListener( Event.ENTER_FRAME, enterframe );
		}
		
		private function enterframe( e:Event ):void
		{
			//回転軸のベクトル
			//xは右、yは下、zは奥方向が正っぽい。
			var rotateAxis:Vector3D = new Vector3D( 0.2, 1.0, 0.1 );
			
			//行列に回転あてるよ。単位はラジアンでなくて度
			_matrix.appendRotation( 1, rotateAxis );
			
			//vertices_inの変換座標が、vertices_outに入るよ
			_matrix.transformVectors( vertices_in, vertices_out );
			
			//描画
			graphics.clear();
			for ( var i:int = 0; i &lt; particle_num ; i++ )
			{
				var vx:Number = vertices_out[i]; i++;
				var vy:Number = vertices_out[i]; i++;
				var vz:Number = 400/(vertices_out[i] + 400);
				graphics.beginFill( 0xffff00 );
				graphics.drawRect( vx*vz, vy*vz, 1, 1 );
				graphics.endFill();
			}
		}
	}	
}
</pre>

<p>
まぁぼちぼち。
</p>

]]>
   </content>
</entry>
<entry>
   <title>Think C</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/102220_think_c.html" />
   <id>tag:nutsu.com,2008:/blog//1.96</id>
   
   <published>2008-10-22T11:34:48Z</published>
   <updated>2008-10-22T11:46:41Z</updated>
   
   <summary> 随分むかしのこと、当時MacはPowerMacで、ThinkCを使ってプログラ...</summary>
   <author>
      <name />
      
   </author>
         <category term="日乗" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<p>
随分むかしのこと、当時MacはPowerMacで、ThinkCを使ってプログラムをしていたことがある。C言語は覚えたばかりで、シンタックスは理解できたけど、Appleのライブラリ？であるToolboxを利用する部分が意味わからんかった思い出がある。
</p>
<p>
プログラム自体は画像ファイルを読み込んで、GUIの操作によって解析するというシンプルなものだったけど、PICTデータを使えるデータに変えたり、GUI周りのプログラムに苦労したような。というより、何かの本を丸写ししたような。WindowsのVisualCを少し書いたことがあるけど、同じような感じで、しばらく大文字に拒否反応が出るくらいだった。大文字で書いてあるやつ意味わからんみたいな。
</p>
<p>
その後登場したJavaは、それらに比べて遙かに見通しがよいと感じた。呪文ではなくロジックを組んでいる感覚。ActionScriptはAPIも少なめなので、やはり見通しがいいと感じた。
</p>
<p>
最近、iPhoneなんかのMacのプログラムとか遊びたいなぁとか思うけど、やっぱりそんな感じなんかなぁと。Toolboxよりか全然わかりやすくなった、とのことだけど。まぁでも、ThinkCも楽しかったなぁ、とか。
</p>
]]>
      
   </content>
</entry>
<entry>
   <title>Matrixのヘルプのこと</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/100913_matrix_adc.html" />
   <id>tag:nutsu.com,2008:/blog//1.95</id>
   
   <published>2008-10-09T04:54:01Z</published>
   <updated>2008-10-09T04:56:29Z</updated>
   
   <summary> ADCに野中先生によるMatrixの解説記事が公開されていました。僕も同じよう...</summary>
   <author>
      <name />
      
   </author>
         <category term="ActionScript" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<p>
ADCに<a href="http://www.adobe.com/jp/devnet/flash/articles/matrix_class.html">野中先生によるMatrixの解説記事</a>が公開されていました。僕も<a href="http://nutsu.com/blog/2008/061320_as_matrix.html">同じようなエントリー</a>を書いたことがありますが、先生の解説に比較して非常にそっけないですね。思いやりがいたらないなぁと。<br/>
それはそれとして、先生は記事の中で「Matrixのヘルプに間違いがある」と指摘していましたが、前から気になっていたのですっきりしました。で、何がというと。
</p>]]>
      <![CDATA[
<p>
Matrixのヘルプには、Matrixの変換行列が以下のように記してあります。
</p>

<p align="center">
<img src="/blog-asset/img/081009_fig_1.png" width="124" height="141" alt="">
</p>

<p>
先生は行列の「b」と「c」が逆ですと指摘しています。
</p>

<p align="center">
<img src="/blog-asset/img/081009_fig_2.png" width="124" height="141" alt="">
</p>

<p>
確かにヘルプ上の行列は間違いなんですが、僕は「tx」と「ty」が間違っていると思ってました。
</p>

<p align="center">
<img src="/blog-asset/img/081009_fig_3.png" width="124" height="141" alt="">
</p>


<p>
（1）と（2）の何が違うのかというと、行列計算するときに変換する座標が式の右か左かということなんですね。
</p>

<p align="center">
<img src="/blog-asset/img/081009_fig_4.png" width="375" height="141" alt="">
</p>
<p align="center">
<img src="/blog-asset/img/081009_fig_5.png" width="375" height="141" alt="">
</p>

<p>
どちらも計算結果は同じですが、変換行列は右からあてる、行列を右に連ねていくというイメージがあるので、どうしても(2)的な解釈をしてしまう。
</p>

<p>
このイメージは3Dの変換行列も同じなのですが、どうも世の変換行列の例とかコーディングは(1)的な考えのものが一般的な気がする。ヘルプの間違いはスッキリしたのですが、(1)か(2)かってところは未だ悶々です。まぁ別にいいんですけど。
</p>]]>
   </content>
</entry>
<entry>
   <title>キューブ(2)</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/100820_f5_cube2.html" />
   <id>tag:nutsu.com,2008:/blog//1.94</id>
   
   <published>2008-10-08T11:40:06Z</published>
   <updated>2008-10-08T11:40:39Z</updated>
   
   <summary> 昨日つくったキューブをミ○ーズブロック風にしてみました。実物は表面のシール？の...</summary>
   <author>
      <name />
      
   </author>
         <category term="何かしら" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<div class="img-label">
<img src="/blog-asset/img/cube2.jpg" width="400" height="245" alt="">
</div>

<p>
昨日つくったキューブを<a href="http://www.amazon.co.jp/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.co.jp%2Fexec%2Fobidos%2FASIN%2FB001AS8TJA&tag=nutsuamazon-22&linkCode=ur2&camp=247&creative=1211">ミ○ーズブロック</a><img src="http://www.assoc-amazon.jp/e/ir?t=nutsuamazon-22&amp;l=ur2&amp;o=9" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />風にしてみました。実物は表面のシール？の質感が多少残念ではありますが、なかなか楽しめます。色ではなくて形をたよりに面を揃えるので、本家版より難しい感じはします。形を見誤って平坦な面にならなかったりとか。回転させるときにもたついたりとか。<br/>
とはいえ、いろいろの形が生まれて興味深いですね。いい感じのときにしっくり置けるスタンド的なものがるといいのですが。
</p>]]>
      <![CDATA[
<p>
とりあえず昨日のキューブの形状を適当に変えてみました。中心の空間が立法体であれば、周辺は好みの形でよいような。
</p>

<script type="text/javascript">
swfObject("cube_2_test","/blog-asset/etu/cube_mirror.swf",425,525,"#202020");
</script>

<p>
なんというか、ポリゴンのZソートって難しいな…。ところどころうまくいってないのが微妙。
</p>

]]>
   </content>
</entry>
<entry>
   <title>キューブ</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/100721_f5_cube.html" />
   <id>tag:nutsu.com,2008:/blog//1.93</id>
   
   <published>2008-10-07T12:36:32Z</published>
   <updated>2008-10-07T12:42:52Z</updated>
   
   <summary> 最近、おフロの開発をぼちぼちと再開していまして、主に3D関連のクラスを触ったり...</summary>
   <author>
      <name />
      
   </author>
         <category term="何かしら" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<div class="img-label">
<img src="/blog-asset/img/cube.jpg" width="400" height="245" alt="">
</div>

<p>
最近、おフロの開発をぼちぼちと再開していまして、主に3D関連のクラスを触ったり眺めたりしているのですが、何かつくってみないことにはデバッグもできんと。で、キューブとかつくっていたりしました。
</p>]]>
      <![CDATA[
<p>
いわゆるキューブですね。操作系とかは全然なんでゲームになりませんが。
</p>

<script type="text/javascript">
swfObject("cube_test","/blog-asset/etu/cube.swf",425,525,"#202020");
</script>

<p>
と遊んでいる内に、やっぱりバグを発見しました。痛いバグもありました。頭も痛いです。
</p>


]]>
   </content>
</entry>
<entry>
   <title>[as]Box2DのJointのテスト</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/091721_as_box2djoint.html" />
   <id>tag:nutsu.com,2008:/blog//1.92</id>
   
   <published>2008-09-17T12:26:09Z</published>
   <updated>2008-09-17T12:29:19Z</updated>
   
   <summary> 最近久しぶりにAS2を触ったりしています。始める前は「ぬぅぅ」とか唸ってました...</summary>
   <author>
      <name />
      
   </author>
         <category term="ActionScript" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<p>
最近久しぶりにAS2を触ったりしています。始める前は「ぬぅぅ」とか唸ってましたが、実際書いてみるとAS2のやわらかい感じが「けっこう楽しいね」とか思ったりとか。今ではFlashDevelopでAS2も書けるし、案外ストレスもないし。<br/>
とAS2とは関係ないですが、Box2Dの回転Jointのテストしてみようと。AS3はライブラリが豊富なのが魅力ですね。<br/>
Box2Dは、<a href="http://box2dflash.sourceforge.net/">Box2DFlashAS3 2.0.1</a>です。
</p>

]]>
      <![CDATA[<p>
今回行ったのは回転Joint(RevoluteJoint)のテストです。何かしらのオブジェクトをドラッグしつつ、クリック座標で回転する的な。とりあえずSWFはこんな感じで。<br/>
小さい「□」はJoint用に用意したオブジェクトです。ドラッグするのは大きい「□」です。
</p>

<script type="text/javascript">
swfObject("box2d_joint_test","/blog-asset/box2d_test_rigid.swf",425,425,"#000000");
</script>

<p>
まず回転Jointは、以下のような手順で書くとよいらしい。定義をつくって実体化って流れがオブジェクトつくるときと同じですね。
</p>

<pre>
//とりあえずJoint定義
var jointDef:b2RevoluteJointDef = new b2RevoluteJointDef();

//つなげるb2Body(オブジェクトの実体)と繋げる位置を指定
jointDef.Initialize( b2body_1, b2body_2, b2Vec2_joint_pos );

//b2Worldインスタンスで実体化する
var joint:b2Joint = b2world.CreateJoint(jointDef);
</pre>

<p>
つないだJointを切り離す場合は、こんな感じ
</p>

<pre>
b2world.DestroyJoint( joint );
</pre>

<p>
以上で何かしらつながる、と。
</p>

<p>
で、マウスでドラッグするようにしたかったので、今回の場合ドラッグの基点(回転の基点)用のダミーオブジェクト(上のサンプルの小さい□)を使ってみた。Jointするには２つのオブジェクトが必要な為です。この方法が正しいの？か知れませんが、表示しなければいいだけなんで、まぁいいかと。
</p>

<p>
次に、ドラッグらしくする為に、マウスの座標とダミーオブジェクトの座標を合わせる必要がある。逆に合わせれば、後の計算をしてくれるので楽。座標の指定は、SetXForm() メソッドでやってみた。他の方法はあるのかなぁ。
</p>

<pre>
//joint_bodyはダミーオブジェクトの実体
//第2引数は回転だったかな…
joint_body.SetXForm( new b2Vec2(x,y), 0 );
</pre>

<p>
最後に、ダミーオブジェクト自体は衝突計算とかしなくてよいので、ShapeDefのfilter使ってみる。
</p>

<pre>
//0にしとくと、どれとも衝突しなくなる。詳しくは b2FilterData
joint_shapeDef.filter.maskBits = 0;
</pre>

<p>
という手順で以下のソースです。ソース中にある、<a href="http://nutsu.com/blog-asset/srcs/Box2DUtil.as">Box2DUtil</a> と <a href="http://nutsu.com/blog-asset/srcs/Box2DElement.as">Box2DElement</a> は前回テストしたとき、割とBox2Dのお約束なのかなぁと思った部分をClassにしたものです。Box2D は手続きが多いのでHelper的な Class があるともっとサクサクつくれるのだろうなぁ。
</p>

<p><strong>TestWorldRigid.as</strong></p>
<pre>
package  
{
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2World;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.Joints.b2RevoluteJointDef;
	import Box2D.Dynamics.Joints.b2Joint;
	import flash.geom.Rectangle;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	/**
	* Box2DなJointテスト
	* @author nutsu
	*/
	public class TestWorldRigid extends MovieClip
	{
		private var world:b2World;
		
		private var jointDef:b2RevoluteJointDef;
		private var joint:b2Joint;
		private var joint_body:b2Body;
		private var rigid_body:b2Body;
		
		private var mouse_pos:b2Vec2;
		
		private var WORLD_SCALE:Number = 100; // 100pixel/m
		private var VIEW_RECT:Rectangle;
		
		public function TestWorldRigid() 
		{
			super();
			
			Box2DUtil.scale = WORLD_SCALE;
			Box2DUtil.usePixelSize = true;
			
			//とりあえずワールドつくる
			world = Box2DUtil.mkWorld();
			
			//静的なオブジェクト（四方壁）をつくる
			VIEW_RECT = new Rectangle( 0, 0, stage.stageWidth, stage.stageHeight );
			Box2DUtil.buildWall( world, VIEW_RECT, 10 );
			
			//動的なオブジェクトつくる
			initObjects();
			
			//テストドローな設定
			Box2DUtil.setDebugDraw( this, world );
			
			//マウス座標用のb2Vec2
			mouse_pos = new b2Vec2( 0, 0 )
			
			//イベント
			addEventListener( Event.ENTER_FRAME, onEnterFrame );
			stage.addEventListener( MouseEvent.MOUSE_DOWN, onMouseDown );
			stage.addEventListener( MouseEvent.MOUSE_UP, onMouseUp );
			
			stage.quality = "low";
		}
		
		private function initObjects():void
		{
			//ドラッグして動かすオブジェクト
			var target_obj:Box2DElement;
			target_obj = new Box2DElement( Box2DUtil.defBox( 40, 80, 1, 0.2 ), 
										   Box2DUtil.defBody( VIEW_RECT.width/2, VIEW_RECT.height/2 ) );
			target_obj.build( world );
			
			//ドラッグ位置でJoint作る用のオブジェクト
			var joint_obj:Box2DElement;
			joint_obj = new Box2DElement( Box2DUtil.defBox( 10, 10, 0 ), 
										  Box2DUtil.defBody( VIEW_RECT.width/2, VIEW_RECT.height/2 ) );
			
			//どれにも衝突しないように
			joint_obj.shapeDef.filter.maskBits = 0;
			joint_obj.build( world );
			
			//あとで使うBody
			rigid_body = target_obj.body;
			joint_body = joint_obj.body;
			
			//とりあえずJoint定義
			jointDef = new b2RevoluteJointDef();
		}
		
		private function onMouseDown( e:MouseEvent ):void
		{
			if ( ! joint )
			{
				//クリック位置をワールド座標へ変換
				mouse_pos.x = mouseX / WORLD_SCALE;
				mouse_pos.y = mouseY / WORLD_SCALE;
				
				//オブジェクト上ならドラッグ処理へ
				if ( rigid_body.m_shapeList.TestPoint( rigid_body.m_xf, mouse_pos ) )
				{
					//スリープしないようにする
					world.m_allowSleep = false;
					
					//スリープ状態を起こす
					if ( rigid_body.IsSleeping() )
						rigid_body.WakeUp();
						
					//ジョイント用のダミーオブジェクトの位置をマウス座標へ
					joint_body.SetXForm( mouse_pos, 0 );
					
					//ジョイントする
					jointDef.Initialize( rigid_body, joint_body, joint_body.GetWorldCenter() );
					joint = world.CreateJoint(jointDef);
				}
			}
		}
		
		
		private function onMouseUp(e:MouseEvent):void 
		{
			if ( joint )
			{
				//ジョイント外す
				world.DestroyJoint( joint );
				joint = null;
				
				//スリープ設定もどす
				world.m_allowSleep = true;
			}
		}
		
		private function onEnterFrame( e:Event ):void
		{
			if ( world )
			{
				if ( joint )
				{
					//ジョイント用のダミーオブジェクトの位置をマウス座標へ
					mouse_pos.x = mouseX / WORLD_SCALE;
					mouse_pos.y = mouseY / WORLD_SCALE;
					joint_body.SetXForm( mouse_pos, 0 );
				}
				//計算
				world.Step( 1/30, 10 );
			}
		}
	}
}
</pre>

<p>
今回のテストを行ってみる際も、Box2Dのソースを見ながら調べていましたが、メソッドとか変数名が分かりやすい印象があります。物理計算という何となく「やること」のイメージがあって、イメージにあった名前が見つかって、あぁやっぱりそうね、みたいな。ライブラリって名前大事だなぁと改めて思った今日この頃でした。とやんわり自戒。
</p>

]]>
   </content>
</entry>
<entry>
   <title>[as]ProxyなAdapter（2）静的アダプタとか</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/082918_as_proxy_adapter2.html" />
   <id>tag:nutsu.com,2008:/blog//1.91</id>
   
   <published>2008-08-29T09:47:01Z</published>
   <updated>2008-09-09T10:39:31Z</updated>
   
   <summary> Spark 勉強会 #2に行けなくて一人スパークしてみようと、昨日エントリーし...</summary>
   <author>
      <name />
      
   </author>
         <category term="ActionScript" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<p>
<a href="http://wiki.libspark.org/wiki/SparkStudy/02">Spark 勉強会 #2</a>に行けなくて一人スパークしてみようと、昨日エントリーした「<a href="http://nutsu.com/blog/2008/082723_as_proxy_adapter.html">ProxyなAdapter</a>」ですが、もう少し便利にしたいなぁということで細々改善してみました。あと、Proxyを継承して動的(dynamic)にしている関係で、指がヌルい僕にとってはFlashDevelopの補完ができずに、まだまだ指ダレしてしまう。なわけで、補完の聞く静的なAdapterをどうにかしようと。静的だといろいろ効率よさそうですし。
</p>]]>
      <![CDATA[<p>なわけで、現状のソースはこれです</p>

<p>
<a href="http://nutsu.com/blog-asset/srcs/src_adapter.zip">adapter classes(src)</a>
</p>

<p>
以下、変わったところについて。
</p>

<h3 class="seq">FAdapter リスナの停止・再開</h3>

<p>前のものは、リスナの停止・再開を abort()、resume()で行うようにしていました。それに加えて以下の書き方でも通るようにしました。</p>

<pre>
var adapter:FAdapter = new FAdapter(stage);
adapter.click = function( e:MouseEvent ):void
{
	trace( "test1", e.type )
};

//停止 adapter.abort("click") と同じ
adapter.click = false;

//再開　adapter.resume("click") と同じ
adapter.click = true;
</pre>


<h3 class="seq">FAdapter 一度きり受ける</h3>

<p>一回のみイベントを受けたい場合(onCompleteとか)がよくあると思うのですが、そんなときはこれ。一度イベントが送出されると自動で removeListener されます。</p>

<pre>
adapter.complete = function( e:Event ):void
{
	trace( e.type );
};

FAdapter.oneTime( adapter.complete );
</pre>

<p>このメソッドは FAdapter の static メソッドです。</p>


<h3 class="seq">FAdapter イベントのフィルタ</h3>

<p>条件付きでイベントを受けたいときもあるだろうということで、そんなときはこれ。filterで指定した関数が true を返すときだけイベントが送出されます。</p>

<pre>
var flg:Boolean = false;
function filter( e:MouseEvent ):Boolean
{
	return flg;
}

FAdapter.filter( adapter.click, filter );
</pre>

<p>このメソッドも FAdapter の static メソッドです。このメソッドには第3引数があって、以下のように書くと、filter関数が false を返すと removeListener されます。</p>

<pre>
var count:int=0;
adapter.mouseDown = function( e:MouseEvent ):void
{
	count++;
	trace( count );
};
function filter( e:MouseEvent ):Boolean
{
	return (count<5);
};

FAdapter.filter( adapter.mouseDown, filter, true );
</pre>

<p>
FAdapter.oneTime(),FAdapter.filter()で条件設定をしたリスナは、以下のようにして条件解除できます。
</p>

<pre>
FAdapter.clearFilter( adapter.mouseDown );
</pre>




<h3 class="seq">静的なアダプタ</h3>

<p>
続いて静的なアダプタについてです。静的なアダプタは、FAbstractFixAdapter クラス を継承することで実現しています。このクラスは、FAdapter を内部に持ち処理を委譲しています。また、抽象クラスのつもりなので、このクラス自体は使いません。実際使う場合のサンプルは、adapters 内を見てください。<br/>
FMouseAdapter クラスを例に簡単に説明してみます。
</p>

<p>
リスナの登録や削除は、FAdapterと若干異なります。異なるというか方法が限定的です。
</p>

<pre>
var adapter:FMouseAdapter = new FMouseAdapter( stage );

function handler( e:MouseEvent ):void
{
	trace(e);
}

//登録
adapter.click = handler;

//停止
adapter.click = false; // or adapter.abort("click");

//再開
adapter.click = true; // or adapter.resume("click");

//削除
adapter.click = null;

//usecaptureなどを設定して登録
adapter.click = adapter.makeListenerInfo( handler, false, 1000, false );

//全削除
adapter.removeAll();

//付け替え
adapter.dispatcher = new AnyDispatcherClass();
</pre>

<p>
一応、FAdapter.oneTime(), FAdapter.filter() を適用することもできます。
</p>

<p>FAdapterにないメソッドとして、bind() があります。これは、targetに該当するメソッドがあれば一括でリスナ登録をするものです。<br/>
※バインドのルールとかいじれるようにしたいけど、今はないです。なのでバインドとは呼べないのでは</p>

<pre>
package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import snapfit.events.adapters.FInteractiveAdapter;
	import snapfit.events.FAdapter;
	
	public class MySprite extends Sprite
	{
		private var adapter:FInteractiveAdapter;
		
		public function MySprite() 
		{
			super();
			adapter = new FInteractiveAdapter(this);
			
			//登録
			adapter.bind(this);
			FAdapter.oneTime( adapter.addedToStage );
			FAdapter.oneTime( adapter.removedFromStage );
		}
		
		public function addedToStage( e:Event ):void
		{
			trace( e );
		}
		
		public function removedFromStage( e:Event ):void
		{
			adapter.removeAll();
			trace( e );
		}
		
		public function enterFrame( e:Event ):void
		{
			trace( e );
		}
	}
	
}
</pre>

<p>この bind() には問題があって、handler関数のスコープ(private等)によっては見えないので登録ができないんです。まぁやっかいでして。今のところ名前空間をあててなんとなくやる感じにしています。</p>

<pre>
package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import snapfit.events.adapters.FInteractiveAdapter;
	import snapfit.events.FAdapter;
	
	//bind用の名前空間
	import snapfit.events.ns_fadapter;
	
	public class MySprite extends Sprite
	{
		private var adapter:FInteractiveAdapter;
		
		public function MySprite() 
		{
			super();
			adapter = new FInteractiveAdapter(this);
			adapter.bind(this);
		}
		
		ns_fadapter function enterFrame( e:Event ):void
		{
			trace( e );
		}
	}
	
}
</pre>

<p>名前空間をあてるにせよ付け焼き刃的対処なので、何かいい方法ないかなぁとか思うのですが。</p>



<h3 class="seq">まとめみたいな</h3>

<p>
課題やデバッグはあれですが何となく使えそうなかたちになってきたかなぁと思ってます。課題は、先の bind の件と一つのイベントタイプにリスナが一つしか登録できないところでしょうか。後のものは大抵１対１だろうからいいのかなぁとは思ってますが、何かいい方法があれば改善しようと。Dictionary使えばなんとかなりそうですが。一応、暫定ですが SparkProject にコミットしておきました。
</p>

<p>
ブラウザ:<br/>
<a href="http://www.libspark.org/browser/as3/snapfit/trunk/src/snapfit/events">http://www.libspark.org/browser/as3/snapfit/trunk/src/snapfit/events</a><br/>
SVN:<br/>
<a href="http://www.libspark.org/svn/as3/snapfit/trunk/src">http://www.libspark.org/svn/as3/snapfit/trunk/src</a>
</p>

<p>
一人スパーク完了。ということで。
</p>
]]>
   </content>
</entry>
<entry>
   <title>[as]ちらっとProxyでAdapterみたいな</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/082723_as_proxy_adapter.html" />
   <id>tag:nutsu.com,2008:/blog//1.90</id>
   
   <published>2008-08-27T14:00:01Z</published>
   <updated>2008-08-27T14:27:44Z</updated>
   
   <summary> 最近、よくProxy関連のエントリーを見るなぁとか思ったのは錯覚なのかわかりま...</summary>
   <author>
      <name />
      
   </author>
         <category term="ActionScript" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="6" label="actionscript" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="21" label="proxy" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<p>
最近、よくProxy関連のエントリーを見るなぁとか思ったのは錯覚なのかわかりませんが、<a href="http://fladdict.net/blog/2008/08/smartdelegate.html">fladdictさんのエントリー</a>がなるほど便利だなぁと思ったわけです。<br/>
で、Proxy使ってみようということで、イベントAdapter的なものを書いてみました。全然＜Proxy＞ぽくないけど。ありがちなので既出のような気もしますが。
</p>]]>
      <![CDATA[<p>
<a href="/blog-asset/srcs/FAdapter.as">FAdapter.as</a>
</p>

<p>
FAdapter クラスの目的は、なにか命題的になっている「イベント処理系をいかにサクッと書くか」「リスナー書くの指だれます」といった課題に何かしらの手段を提供するものです。特にaddEventListenerとか、removeEventListenerやらが対象です。
</p>

<h3 class="seq">リスナの登録</h3>

<p>リスナの登録は以下のようにして書きます。</p>

<pre>
//対象になるEventDispatcherを指定
var adapter:FAdapter = new FAdapter(stage);

//登録
adapter.click = function( e:MouseEvent ):void
{
	trace( "test1", e.type )
};
</pre>

<p>
登録はAS2のような書き方ですね。adapter.* の部分にイベントタイプを指定するわけです。書き換えるとこんな感じ。
</p>

<pre>
adapter[MouseEvent.CLICK] = function( e:MouseEvent ):void
{
	trace( "test1", e.type )
};
</pre>

<p>
propertyで指定するので以下のような書き方もできます。
</p>

<pre>
adapter.click = adapter.mouseDown = function( e:MouseEvent ):void
{
	trace( "test1", e.type )
};
</pre>

<p>
useCapture、weakReferenceなどを指定する場合は以下の通り。
</p>

<pre>
//イベントタイプをメソッド名にして指定。handler以外は省略可
adapter.click( handler, capture, priority, weakReference );

//ノーマルにも書けます
adapter.addEventListener( type, handler, capture, priority, weakReference );
</pre>


<h3 class="seq">リスナの削除関係</h3>

<p>リスナの削除は以下のようにして書きます。</p>

<pre>
delete adapter.click;

//あるいは
adapter.click = null;

//普通に消す場合の方法
adapter.removeEventListener("click");

//全削除
adapter.removeAll();
</pre>

<p>一応、停止と再開もできます。引数にイベントタイプを入れます。省略すると対象が全部になります。</p>

<pre>
//停止
adapter.abort("click");

//再開
adapter.resume("click");
</pre>

<h3 class="seq">アダプター的なところ</h3>

<p>アダプター的なところは以下ような書き方です。</p>

<pre>
//対象はとりあえずなしでもいけます
var adapter:FAdapter = new FAdapter();
adapter.click = function( e:MouseEvent ):void
{
	trace( "test1", e.type )
};

//あとで付ける
adapter.dispatcher = stage;
</pre>

<h3 class="seq">補足</h3>

<p>adapter.eventType で返されるオブジェクトは $listener(FAdapter の innerClass) です。このオブジェクトのpropertyでリスナの情報が見れます(読みのみ)。</p>

<ul>
<li>adapter.eventType.type</li>
<li>adapter.eventType.handler</li>
<li>adapter.eventType.useCapture</li>
<li>adapter.eventType.priority</li>
<li>adapter.eventType.useWeakReference</li>
<li>adapter.eventType.active ( :Boolean abort中はfalse )</li>
</ul>

<h3 class="seq">まとめみたいな</h3>

<p>
以上、全然Proxyの目的に沿ってないようですが、Proxyの動的な部分に注目して書いてみました。例外処理とか怪しいし改善点も多いですが、はじめての Proxy ということで。使いながらデバッグとか改善とかできればいいかと。一番の問題点は、当然ですが FlashDevelop などで入力補助がでないところ…です。
</p>
]]>
   </content>
</entry>
<entry>
   <title>[as]ちらっとBox2D</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/082521_as_box2d_first.html" />
   <id>tag:nutsu.com,2008:/blog//1.89</id>
   
   <published>2008-08-25T12:59:56Z</published>
   <updated>2008-08-25T13:00:45Z</updated>
   
   <summary> いまさらながらBox2Dを勉強してみる。物理計算(特に力学系)をやる場合、毎回...</summary>
   <author>
      <name />
      
   </author>
         <category term="ActionScript" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="6" label="actionscript" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="20" label="box2d" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<p>
いまさらながらBox2Dを勉強してみる。物理計算(特に力学系)をやる場合、毎回必要な分だけ生書きしてたのですが、やはりライブラリ使ったほうが効率的かなぁ(特にプロトタイプとか)、という当たり前な理由でまずは触ってみようということで。<br/>
勉強するにあたって「<a href="http://www.amazon.co.jp/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.co.jp%2FFLASH-OOP-ActionScript-Flash-Japan%2Fdp%2F4798116300%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1219667601%26sr%3D8-1&tag=nutsuamazon-22&linkCode=ur2&camp=247&creative=1211">Flash OOP本</a><img src="http://www.assoc-amazon.jp/e/ir?t=nutsuamazon-22&amp;l=ur2&amp;o=9" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />の10章」と、「<a href="http://gihyo.jp/dev/feature/01/box2d">Box2DでActionScript物理プログラミング</a>」にお世話になります。わかりやすいなぁ。<br/>
使用したのは、いつのまにかバージョンが上がっていた、<a href="http://box2dflash.sourceforge.net/">Box2DFlashAS3 2.0.1</a>です。
</p>
]]>
      <![CDATA[
<p>
上記「OOP本」と「Box2DでActionScript物理プログラミング」を眺めるに、大体の流れは、
</p>

<p>
1.ワールドをつくる<br/>
2.BodyなDefとShapeなDefで位置とか形状をつくる<br/>
3.BodyとShapeの実体をつくる<br/>
4.計算してみる<br/>
5.表示に反映させる
</p>

<p>
ってことみたいですね(今回はJointとか衝突イベントやってないです)。「5.表示に反映させる」については、テスト用に「b2DebugDraw」というクラスがあるので、それを使えばすぐに確認できてお手軽です。<br/>
※「OOP本」はBox2Dのバージョンがわかりませんが1.x系なんでしょうか、ちょっとメソッドとか異なるようです。でも流れは同じようなので参考になります。「Box2DでActionScript物理プログラミング」のほうは 2.0.0 なのでそのままいけそうなんですが、b2World の CreateStaticBody,CreateDynamicBodyが 2.0.1 ではなくなってる様子。CreateBodyにしとけば大丈夫ぽい。
</p>

<p>
で、とりあえず試してみたかったのは、重加速度とShape属性(サイズとか)の動的変更で、その辺りはBox2Dのソースを追いながらアテを探してみることに。ソースを追うにはFlashDevelopが便利ですね。しばらく見たところ、重加速度は、b2World の m_gravity 、Shapeの属性は「3.BodyとShapeの実体をつくる」でつくったb2Shapeから辿ればいけるっぽい。感じ。
</p>

<p>
そんな流れでつくってみた、ちょっと気持ち悪いBox2Dのサンプルです。
</p>

<script type="text/javascript">
swfObject("box2d_test","/blog-asset/box2d_test.swf",425,425,"#000000");
</script>

<p>
マウスの位置で重加速度が変化して、クリックで円が増えます。で、円をsinで大きさを変えてます。ソースは以下のような感じ。
</p>

<p><strong>TestWorld.as</strong></p>
<pre>
package  
{
	import Box2D.Collision.b2AABB;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2World;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Collision.Shapes.b2PolygonDef;
	import Box2D.Collision.Shapes.b2CircleDef;
	import Box2D.Dynamics.b2Body;
	import Box2D.Collision.Shapes.b2Shape;
	import Box2D.Collision.Shapes.b2CircleShape;
	import Box2D.Dynamics.b2DebugDraw;
	import flash.geom.Rectangle;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	/**
	* Box2Dなテスト
	* @author nutsu
	*/
	public class TestWorld extends MovieClip
	{
		private var world:b2World;
		
		private var WORLD_SCALE:Number = 100; // 100pixel/m
		private var VIEW_RECT:Rectangle;
		private var half_width:Number;
		private var half_height:Number;
		
		private var circles:Array;
		
		public function TestWorld() 
		{
			super();
			
			VIEW_RECT   = new Rectangle( 0, 0, stage.stageWidth/WORLD_SCALE, stage.stageHeight/WORLD_SCALE );
			half_width  = stage.stageWidth * 0.5;
			half_height = stage.stageHeight * 0.5;
			
			//動的オブジェクト用の配列 :b2CircleShape[]
			circles = [];
			
			//とりあえずワールドつくる
			initWorld();
			//静的なオブジェクト（四方壁）をつくる
			initObjects();
			//テストドローな設定
			initDraw();
			//とりあえず１こオブジェクトつくる
			addCircle( VIEW_RECT.width*0.5, VIEW_RECT.height*0.5 );
			
			addEventListener( Event.ENTER_FRAME, onEnterFrame );
			stage.addEventListener( MouseEvent.CLICK, onClick );
			
			stage.quality = "low";
		}
		
		private function initWorld():void
		{
			//物理計算エリア？　お約束らしい
			var aabb:b2AABB = new b2AABB();
			aabb.lowerBound.Set( -1000, -1000 );
			aabb.upperBound.Set( 1000, 1000 );
			
			//重加速度。後でマウス位置で変えるので０にしとく
			var gravity:b2Vec2 = new b2Vec2( 0, 0 );
			
			//力が作用してないオブジェクトをスリープするか否か。今回はずっと動いてるのでfalse
			var dosleep:Boolean = false;
			
			//ワールドつくる
			world = new b2World( aabb, gravity, dosleep );
		}
		
		private function initObjects():void
		{
			//四方壁つくる
			//大きさの単位はメートルなそうな
			var wall_size:Number = 0.025;
			
			//ShapeなDef（形状決め）
			var wall_side_shape:b2PolygonDef = new b2PolygonDef();
			wall_side_shape.SetAsBox( wall_size, VIEW_RECT.height * 0.5 );
			wall_side_shape.density = 0; //静的な物体は0なそうな
			
			var wall_vt_shape:b2PolygonDef = new b2PolygonDef();
			wall_vt_shape.SetAsBox( VIEW_RECT.width*0.5, wall_size );
			wall_vt_shape.density = 0;
			
			//BodyなDef（位置決め）
			var wall_left:b2BodyDef   = new b2BodyDef();
			var wall_right:b2BodyDef  = new b2BodyDef();
			var wall_bottom:b2BodyDef = new b2BodyDef();
			var wall_top:b2BodyDef    = new b2BodyDef();
			
			//set position
			wall_left.position.Set(  wall_size, VIEW_RECT.height * 0.5 );
			wall_right.position.Set( VIEW_RECT.width - wall_size, VIEW_RECT.height * 0.5 );
			wall_bottom.position.Set( VIEW_RECT.width * 0.5 , VIEW_RECT.height - wall_size);
			wall_top.position.Set( VIEW_RECT.width*0.5 ,  wall_size);
			
			//worldに入れてく
			world.CreateBody( wall_left   ).CreateShape( wall_side_shape );
			world.CreateBody( wall_right  ).CreateShape( wall_side_shape );
			world.CreateBody( wall_bottom ).CreateShape( wall_vt_shape );
			world.CreateBody( wall_top    ).CreateShape( wall_vt_shape );
		}
		
		private function initDraw():void
		{
			//デバッグ用のドロー設定
			var debug_draw:b2DebugDraw = new b2DebugDraw();
			debug_draw.m_sprite        = this;
			debug_draw.m_drawScale     = WORLD_SCALE;
			debug_draw.m_fillAlpha     = 1;
			debug_draw.m_lineThickness = 0;
			debug_draw.m_drawFlags     = b2DebugDraw.e_shapeBit;
			world.SetDebugDraw( debug_draw );
		}
		
		private function addCircle( ax:Number, ay:Number ):void
		{
			//任意の位置にCircleオブジェクト追加してく
			//手順　ShapeなDef→BodyなDef→worldで実体をつくる感じ
			var s:b2CircleDef = new b2CircleDef();
			s.density = 1;
			s.restitution = 0.2;
			s.radius = 0.2;
			
			var b:b2BodyDef = new b2BodyDef();
			b.position.Set( ax, ay );
			
			var bb:b2Body  = world.CreateBody( b );
			var bs:b2Shape = bb.CreateShape( s );
			bb.SetMassFromShapes();
			
			//Shapeはあとでいじるので配列にいれとく
			bs.m_userData = Number(0);
			circles.push( b2CircleShape(bs) );
		}
		
		private function onClick( e:MouseEvent ):void
		{
			addCircle(mouseX/WORLD_SCALE, mouseY/WORLD_SCALE);
		}
		
		private function onEnterFrame( e:Event ):void
		{
			if ( world )
			{
				//マウス位置で重加速度変更
				world.m_gravity.x = -2 * (half_width - mouseX) / half_width;
				world.m_gravity.y = -2 * (half_height - mouseY) / half_height;
				
				//円をうにょうにょ
				for (var i:int = 0; i &lt; circles.length ; i++) 
				{
					var bs:b2CircleShape = circles[i];
					bs.m_radius = 0.2 + Math.sin( bs.m_userData ) * 0.1;
					bs.m_userData += 0.05;
				}
				
				//計算　Step(計算時間,計算精度)　きびっとしたいので計算時間を長めにとる
				world.Step(1/15, 4);
			}
		}
	}
}
</pre>

<p>なんと言いますか、お手軽だなぁという印象です。ライブラリって便利。</p>

<p>
誰かに向けたメモ：<br/>
Box2Dのソースみていると、virtual があるんですが、AS に virtual ってあったんですか？自分で書いてみたらコンパイル通るみたいなんですけど、何か意味あるのかな…。
</p>]]>
   </content>
</entry>
<entry>
   <title>[as]Matrix の scale と rotate のこと</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/080720_matrix_extest.html" />
   <id>tag:nutsu.com,2008:/blog//1.88</id>
   
   <published>2008-08-07T11:17:05Z</published>
   <updated>2008-08-07T11:22:27Z</updated>
   
   <summary> frocessingでは、Matrixを拡張してFMatrix2Dというクラス...</summary>
   <author>
      <name />
      
   </author>
         <category term="ActionScript" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="6" label="actionscript" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="18" label="matrix" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<p>
frocessingでは、Matrixを拡張してFMatrix2Dというクラスをつくっているのですが、その過程でどうもオリジナルの matrix.scale() と Matrix.rotate() が遅いんじゃないかと思いまして、以下試してみたものです。
</p>]]>
      <![CDATA[<p>
とりあえずテスト用につくったもので、オリジナル(ori)と scale,translate,rotateをoverrideして実装しなおしたもの(ext)を、それぞれfor文でまわしたものです。影響が出そうな、createBox, createGradientBox についても比較しています。それぞれ10万回実行しています。
</p>

<script type="text/javascript">
swfObject("matrixex","/blog-asset/matrix_ex.swf",425,200,"#000000");
</script>

<p>
自分の環境では、translateは大体同じだけど、scale と rotate 及び影響が出ていると思われる box系で随分処理時間に差が出ています。どうでしょうか？
</p>

<p>
実際には10万回なんて実行しないので、現実的には差がないように思えますが、とりあえずメモということで。
</p>

<p>
以下実装し直した TestMatrix と 上のテストで使用したスクリプトです。
</p>

<p><strong>TestMatrix.as</strong></p>
<pre>
package{
	
	import flash.geom.Matrix;
	
	public class TestMatrix extends Matrix
	{
		
		public function TestMatrix( a_:Number=1, b_:Number=0, c_:Number=0, d_:Number=1, tx_:Number=0, ty_:Number=0)
		{
			super( a_, b_, c_, d_, tx_, ty_ );
		}
		
		override public function translate( dx:Number, dy:Number ):void
		{
			//(1,0,0,1,dx,dy)
			tx += dx;
			ty += dy;
		}
		
		override public function scale( sx:Number, sy:Number ):void
		{
			//(sx,0,0,sx,0,0)
			a  *= sx;
			b  *= sy;
			c  *= sx;
			d  *= sy;
			tx *= sx;
			ty *= sy;
		}
		
		override public function rotate( angle:Number ):void
		{
			//(c, s, -s, c, 0, 0)
			var sin:Number = Math.sin(angle);
			var cos:Number = Math.cos(angle);
			var n11:Number = a * cos - b * sin;
			var n12:Number = a * sin + b * cos;
			var n21:Number = c * cos - d * sin; 
			var n22:Number = c * sin + d * cos;
			var n31:Number = tx * cos - ty * sin; 
			var n32:Number = tx * sin + ty * cos;
			a  = n11; b  = n12;
			c  = n21; d  = n22;
			tx = n31; ty = n32;
		}
	}
}
</pre>

<p><strong>テストコード</strong></p>
<pre>
//ベタなテストですいません
//out_txtはTextFieldです

var n:int = 50000;
var t:int;
var i:int;

var fmt:TestMatrix = new TestMatrix( 1, 2, 3, 4, 5, 6 );
var mt:Matrix = new Matrix( 1, 2, 3, 4, 5, 6 );

//---------------------------------------------
out_txt.appendText( "[SCALE]");

t = getTimer();
for( i=0; i&lt;n; i++ )
{
	mt.scale( 10, 10 ); mt.scale( 0.1,0.1 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i&lt;n; i++ )
{
	fmt.scale(10,10); fmt.scale(0.1,0.1);
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

//---------------------------------------------
out_txt.appendText( "\n[TRANSLATE]");
t = getTimer();
for( i=0; i&lt;n; i++ )
{
	mt.translate( 10, 10 ); mt.translate( -10,-10 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i&lt;n; i++ )
{
	fmt.translate(10,10); fmt.translate(-10,-10);
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

//---------------------------------------------
out_txt.appendText( "\n[ROTATE]");
t = getTimer();
for( i=0; i&lt;n; i++ )
{
	mt.rotate( 1.5 ); mt.rotate( -1.5 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i&lt;n; i++ )
{
	fmt.rotate(1.5); fmt.rotate(-1.5);
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

//---------------------------------------------
out_txt.appendText( "\n[CREATE_BOX]");
t = getTimer();
for( i=0; i&lt;n; i++ )
{
	mt.createBox( 10, 10, 1, 1, 1 );
	mt.createBox( 0.1, 0.1, -1, -1, -1 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i&lt;n; i++ )
{
	fmt.createBox( 10, 10, 1, 1, 1 );
	fmt.createBox( 0.1, 0.1, -1, -1, -1 );
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

//---------------------------------------------
out_txt.appendText( "\n[CREATE_GRADIENT_BOX]");
t = getTimer();
for( i=0; i&lt;n; i++ )
{
	mt.createGradientBox( 10, 10, 1, 1, 1 );
	mt.createGradientBox( 0.1, 0.1, -1, -1, -1 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i&lt;n; i++ )
{
	fmt.createGradientBox( 10, 10, 1, 1, 1 );
	fmt.createGradientBox( 0.1, 0.1, -1, -1, -1 );
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );
</pre>

<p>テストの方法が微妙な気がしますが、いいベンチマークの方法があったら知りたい…</p>

]]>
   </content>
</entry>
<entry>
   <title>Spark project 勉強会 #01 いってきました</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/072419_sparkstudy01.html" />
   <id>tag:nutsu.com,2008:/blog//1.87</id>
   
   <published>2008-07-24T10:13:13Z</published>
   <updated>2008-07-24T10:26:17Z</updated>
   
   <summary> 7/22に開催されたSpark project 勉強会 #01に行ってまいりま...</summary>
   <author>
      <name />
      
   </author>
         <category term="ActionScript" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="6" label="actionscript" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="17" label="frocessing" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="19" label="spark" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<div class="img-label">
<img src="/blog-asset/img/f5.png" width="400" height="230" alt="">
</div>

<p>
7/22に開催された<a href="http://wiki.libspark.org/wiki/SparkStudy/01">Spark project 勉強会 #01</a>に行ってまいりました。拙いながら発表までさせていただいてありがたい限りです。<br/>
他の方の発表内容は非常に勉強になる上、プレゼンの仕方自体も勉強になって反省反省です。というか喋る前から反省モードでしたが。<br/>
とはいえ、自戒の意味もこめて使用した発表資料をアップしたいと思います。他の方と比べて明かにスライド数が少ないし、スライドだけ見ても意味不明なのはこれからの精進ということで。
</p>

<p>
<a href="http://nutsu.com/spark/spark01_slides.html">http://nutsu.com/spark/spark01_slides.html</a>
</p>

<p>
みなさんのあたたかさに救われた今日この頃です。感謝感謝です。
</p>]]>
      
   </content>
</entry>
<entry>
   <title>RADIOHEADのアレ</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/071720_radiohead.html" />
   <id>tag:nutsu.com,2008:/blog//1.86</id>
   
   <published>2008-07-17T11:21:20Z</published>
   <updated>2008-07-24T06:01:42Z</updated>
   
   <summary> RADIOHEADのアレ( RA DIOHEA_D / HOU SE OF_C...</summary>
   <author>
      <name />
      
   </author>
         <category term="何かしら" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="6" label="actionscript" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="17" label="frocessing" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<p>
RADIOHEADのアレ( <a href="http://code.google.com/creative/radiohead/">RA DIOHEA_D / HOU SE OF_C ARDS - Google Code</a> )を僕もやってみた。データの説明とかあまり見てないので色のデータが？？だけど、とりあえず僕のところにもトムヨーク増やしてみました。
</p>]]>
      <![CDATA[<p>
BitmapData の setPixel32() です。
</p>

<script type="text/javascript">
swfObject("radiohead_test","/blog-asset/etu/radiohead/radiohead_test.swf",425,600,"#000000");
</script>

<p>
それにしても重い…。しばらく回しているとろくろ首にみえてきた…。もっといろいろあそんでみたい。
</p>

<p>
<strong>追記</strong><br/>
なんだか、<a href="http://blog.r3c7.net/?p=209">note.xさん</a>、<a href="http://www.metaphor.co.jp/masuda/blog/?p=21">MASDAさん</a>、からリンクを張っていただいて恐縮しております。僕のサンプルは、frocessingのテストでつくってたやつなので、ソースを上げておくことにしました。以下ソースです。
</p>

<pre>
package
{
	import flash.display.MovieClip;
	import flash.display.StageQuality;
	import org.libspark.thread.Thread;
	import org.libspark.thread.EnterFrameThreadExecutor;
	
	[SWF(width=425, height=600, frameRate=30, backgroundColor=0x000000)]
	public class TestPlot extends MovieClip
	{
		public function TestPlot()
		{
			stage.quality   = StageQuality.LOW;
			Thread.initialize(new EnterFrameThreadExecutor());
			new TestPlotThread(this).start();
		}
	}
}

import flash.display.Sprite;
import flash.display.Bitmap;
import flash.filters.BlurFilter;
import flash.net.URLRequest;
import flash.geom.Point;
import flash.errors.IOError;

import org.libspark.thread.Thread;
import org.libspark.thread.threads.net.URLLoaderThread;

import frocessing.core.F5BitmapData3D;
import frocessing.geom.FNumber3D;
import frocessing.math.FMath;

class TestPlotThread extends Thread
{
	private var _target:Sprite;
	private var fg:F5BitmapData3D;
	
	var w:Number = 425;
	var h:Number = 600;
	
	var dataloader:URLLoaderThread;
	var vertexs:Array;
	var colors:Array;
	
	public function TestPlotThread( target:Sprite )
	{
		_target = target;
		fg = new F5BitmapData3D( w, h, false, 0x01000000 );
		_target.addChild( new Bitmap( fg.bitmapData, "auto", true  ) );
	}
	
	override protected function run():void
	{
		var datauri:String = "1.csv";
		dataloader = new URLLoaderThread(new URLRequest(datauri))
		dataloader.start();
		dataloader.join();
		
		next(setup);
		
		error(IOError, errorHandler);
		error(SecurityError, errorHandler);
	}
	
	protected function setup():void
	{
		var dats:Array = dataloader.loader.data.split("\r\n");
		
		vertexs = [];
		colors  = [];
		var len:int = dats.length;
		var d:Array;
		var r:int;
		var g:int;
		for ( var i:int; i &lt; len; i++ )
		{
			d = dats[i].split(",");
			r = Math.min( 0xff, (int(d[3]) + 50) );
			g = Math.min( 0xff, (int(d[3]) + 100) );
			vertexs[i] = new FNumber3D( Number(d[0]), Number(d[1]), Number(d[2]) );
			colors[i]  = r &lt;&lt; 16 | g &lt;&lt; 8 | 0xff;
		}
		
		fg.background( 0, 0.2 );
		fg.strokeAlpha = 0.5;
		
		next(draw);
	}
	
	var blurfilter:BlurFilter = new BlurFilter( 4 );
	var zp:Point = new Point();
	var camera_z:Number = 100;
	var _pan:Number = 0;
	var _pth:Number = 0;
	
	protected function draw():void
	{
		fg.bitmapData.applyFilter( fg.bitmapData, fg.bitmapData.rect, zp, blurfilter );
		fg.beginDraw();
		
		camera_z += ( 100 + _target.mouseY  - camera_z ) * 0.5;
		_pan += ( -FMath.radians( _target.mouseX - w/2 )*1.5 - _pan  ) * 0.2;
		_pth += ( -FMath.radians( _target.mouseY - h/2 )*0.05 - _pth ) * 0.2;
		
		fg.camera( w/2, h/2, camera_z );
		fg.translate( w/2, h/4, 0);
		
		fg.rotateY( _pan );
		fg.rotateX( _pth );
		
		var len:int = vertexs.length;
		var vt:FNumber3D;
		for ( var i:int = 0; i &lt; len ; i++ )
		{
			fg.strokeColor = colors[i];
			vt = vertexs[i];
			fg.pixel( vt.x, vt.y, vt.z );
		}
		
		fg.endDraw();
		
		next(draw);
	}
	
	private function errorHandler(e:IOError, t:Thread):void
	{
		trace("Thread Error.");
		trace(e.getStackTrace());
		next(null);
	}
}
</pre>

<p>
いい加減、きれいにソースを貼ることを考えなくちゃいけない…と思いました。
</p>]]>
   </content>
</entry>
<entry>
   <title>[f5]簡単なtextureを描画できるようにしてみた</title>
   <link rel="alternate" type="text/html" href="http://nutsu.com/blog/2008/063020_f5_texturetest.html" />
   <id>tag:nutsu.com,2008:/blog//1.85</id>
   
   <published>2008-06-30T11:59:01Z</published>
   <updated>2008-07-15T12:09:36Z</updated>
   
   <summary> 相変わらずおフロをごにょごにょしております。 さて、Processing には...</summary>
   <author>
      <name />
      
   </author>
         <category term="ActionScript" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="6" label="actionscript" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="17" label="frocessing" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://nutsu.com/blog/">
      <![CDATA[<p>
相変わらずおフロをごにょごにょしております。<br/>
さて、Processing には texture というメソッドがあって、画像をuv指定で Triangle や Quad を描画できるのですが、その辺り、Astro の drawTriangles メソッドを使うと楽なので、Astroさん待ちかなぁ、と思っていたのですが、やっぱりできたほうがいいなぁと思って限定的ながら実装してみました。<br/>
その関係で、drawTriangles もどきなメソッドも実装してみました。
</p>]]>
      <![CDATA[<p>
texure を貼り付けた 3D描画はこんな感じです。
</p>

<script type="text/javascript">
swfObject("texture_test","/blog-asset/etu/texture_test.swf",425,425,"#ffffff");
</script>

<p>
画像はPapervisionのサンプルを使わさせていただいています。（※問題あれば変えます。と誰となく)
</p>

<p>
上のサンプルのコードはこんな感じです。
</p>

<pre>
import flash.display.Shape;
import flash.events.Event;
import frocessing.core.F5Graphics3D;
import frocessing.f3d.model.F3DSphere;
import frocessing.math.FMath;

var w:Number = stage.stageWidth;
var h:Number = stage.stageHeight;
var a:Number = 0;
var camera_pan:Number = 0;
var camera_pth:Number = 0;

var sp:Shape = Shape( addChild(new Shape()) );
var fg:F5Graphics3D = new F5Graphics3D( sp.graphics, w, h );

var earth:F3DSphere = new F3DSphere( 30, 12 );
earth.setTexture( new Earth(0,0) );

var bgspace:F3DSphere = new F3DSphere( 400, 12 );
bgspace.setTexture( new Space(0,0) );

stage.quality = "medium";

fg.noStroke();

function draw( e:Event ):void
{
	fg.beginDraw();
	
	camera_pan += ( FMath.radians( mouseX - w/2 ) - camera_pan )*0.2;
	camera_pth += ( FMath.radians( mouseY/2 ) - camera_pth )*0.2;
	
	var camera_x:Number = 100.0*Math.cos( camera_pan );
	var camera_y:Number = 100.0*Math.cos( camera_pth );
	var camera_z:Number = 100.0*Math.sin( camera_pan );
	fg.camera( w/2 + camera_x, h/2 + camera_y, camera_z );
	
	fg.translate(w/2, h/2, 0);
	
	fg.pushMatrix();
	fg.rotateY( -a*0.2 );
	fg.backFaceCulling = false;
	fg.model( bgspace );
	fg.popMatrix();
	
	fg.rotateY( a );
	fg.backFaceCulling = true;
	fg.model( earth );
	
	a += 0.01;
	
	fg.endDraw();
}

addEventListener( Event.ENTER_FRAME, draw );
</pre>

<p>
frocessing.display.F5MovieClip3D を DocumentClass にした場合はこんな感じ。ちょと簡単に見えます。
</p>

<pre>
var w:Number = fg.width;
var h:Number = fg.height;
var a:Number = 0;

var camera_pan:Number = 0;
var camera_pth:Number = 0;

var earth:F3DSphere = new F3DSphere( 30, 12 );
earth.setTexture( new Earth(0,0) );

var bgspace:F3DSphere = new F3DSphere( 400, 12 );
bgspace.setTexture( new Space(0,0) );

QMedium();
noStroke();

function draw():void
{
	camera_pan += ( radians( mouseX - w/2 ) - camera_pan )*0.2;
	camera_pth += ( radians( mouseY/2 ) - camera_pth )*0.2;
	
	var camera_x:Number = 100.0*cos( camera_pan );
	var camera_y:Number = 100.0*cos( camera_pth );
	var camera_z:Number = 100.0*sin( camera_pan );
	camera( w/2 + camera_x, h/2 + camera_y, camera_z );
	
	translate(w/2, h/2, 0);
	
	pushMatrix();
	rotateY( -a*0.2 );
	fg.backFaceCulling = false;
	model( bgspace );
	popMatrix();
	
	rotateY( a );
	fg.backFaceCulling = true;
	model( earth );
	
	a += 0.01;
}
</pre>

<p>
3D関係をごにょごにょしている関係で、ソースがわりと荒れているのですが、ぼちぼち落ち着けていきたいです。あと、となりの人の意見など聞きながら、3D関連のクラス名とかメソッド名とか変わりそう。
</p>

<p>
個人的には、FBitmapGraphics や FMatrix2D.createUVBox() あたりが便利に使えるのかなぁとか思ったりしてますが、どうでしょうか。drawTriangles もどきは、F5Graphics3D.drawBitmapTriangles() あたりです。
</p>

<p>
なんだか PV3D やら Away3D やらあるから今更いいじゃないかって向きもあると思いますが、ぼちぼち楽しんでやっております。
</p>

<p>
追記：ちょっと3Dまわりを整理して、backfacecullingを入れたので若干ソースを修正しました。（2008/7/15）
</p>
]]>
   </content>
</entry>

</feed>
