<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>MOROCOSHI:BLOG</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/" />
    <link rel="self" type="application/atom+xml" href="http://www.morocoshi.net/blog/atom.xml" />
    <id>tag:http://www.morocoshi.net/blog/</id>
    <updated>2009-11-22</updated>
    <subtitle>フリーダムに生きてゆきます</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.261</generator>

<entry>
    <title>ふんふん</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/11/post.html" />
    <id>http://www.morocoshi.net/blog/2009/11/post.html</id>

    <published>2009-11-22</published>
    <updated>2009-11-22</updated>

    <summary>最近ちょっと更新が滞ってます。バンドの手伝いとか、手伝いじゃないのとか、色々もさ...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="Life" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[最近ちょっと更新が滞ってます。<br />バンドの手伝いとか、手伝いじゃないのとか、色々もさもさしてて。<br /><br />久しぶりに記事みなおしてみると色々直したいとこがあるなあ。。<br />とりあえず気になったのは、<a href="http://www.morocoshi.net/blog/2009/10/pv3d21.html">レンズフレア</a>の記事で<br />もしかして黒に塗ってる意味ない？とか、<br />記事ではチャンネルコピーしてるけど<br />画像そのままコピーしてぼかしてアルファ値調べればいいだけ？とか・・・<br />負荷はあまり変わらないのかもしれないけどね。<br />落ち着いたら修正するかもしれません。<br />]]>
        
    </content>
</entry>

<entry>
    <title>wmodeを指定するとMOUSE_LEAVEが効かない場合がある？</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/11/wmodetran.html" />
    <id>http://www.morocoshi.net/blog/2009/11/wmodetran.html</id>

    <published>2009-11-11</published>
    <updated>2009-11-11</updated>

    <summary>ステージ内でマウスを押した(MOUSE_DOWN)ままFlashの領域外までドラ...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="ActionScript3" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[ステージ内でマウスを押した(MOUSE_DOWN)ままFlashの領域外までドラッグした時、<br />そのままではマウスを離したイベント(MOUSE_UP)を検出できないんだけど<br />マウスがFlash領域から出た時を検出できるEvent.MOUSE_LEAVEを使うと<br />マウスダウン→領域外までドラッグ→マウスアップのタイミングでもイベントが取れるので<br />これを利用してボタンの表示を元に戻したりドラッグ処理を停止したりできます。<br />ただswfをhtmlに埋め込む時にwmodeを指定していると<br />環境によってはMOUSE_LEAVEイベントが発生しない事があるっぽい。。。<br /><br />ので、検証用にサンプルを用意してちょっと実験してみました。<br />全部WindowsXP、FlashPlayer10でテストしてます。ブラウザは4つだけ。<br /><br />真ん中の黒いボックスがボタンになってて、<br />マウスを押すとオレンジに、離すと青に変化するようになってます。<br />「ボタン上でマウスダウン→Flash領域外までドラッグ→マウスを離す」ってやって<br />オレンジ→青と変われば成功ね。<br /><br />
<h3>wmode指定なし</h3>
<div id="swf1"></div><br />
IE8・Firefox3.0・Opera10・Safari4で全部問題なし。<br /><br />
<script type="text/javascript">
swfobject.embedSWF("http://www.morocoshi.net/blog/material/swf/mouseleave.swf", "swf1", 200, 200, "9", "", {}, {});
</script>
<h3>wmode=transparent</h3>
<div id="swf2"></div><br />
Firefox3.0・Opera10・Safari4では領域外ドラッグでMOUSE_LEAVEが効かない。<br />挙動も色々おかしい気がする。<br />IE8では領域外(ブラウザ内)でマウスを離すと何故かstageのMOUSE_UPが発生して<br />その後領域外でマウスを動かすとMOUSE_LEAVEが発生した。<br />IE8でドラッグしてブラウザの外で離すとすぐにMOUSE_LEAVEが発生。<br /><br />
<script type="text/javascript">
swfobject.embedSWF("http://www.morocoshi.net/blog/material/swf/mouseleave.swf", "swf2", 200, 200, "9", "", {}, {wmode: "transparent"});
</script>
<h3>wmode=opaque</h3>
<div id="swf3"></div><br />
transparentと同じ結果。<br /><br />
<script type="text/javascript">
swfobject.embedSWF("http://www.morocoshi.net/blog/material/swf/mouseleave.swf", "swf3", 200, 200, "9", "", {}, {wmode: "opaque"}); </script><br /><h3>結局</h3>MOUSE_LEAVEを判定したい時はwmodeは指定すると駄目って事なのかな。<br />見にくいけどサンプルのソースは<a target="_blank" href="http://www.morocoshi.net/blog/material/as/MouseLeaveTest.as">これです</a><br />]]>
        
    </content>
</entry>

<entry>
    <title>PV3D2.1: FrustumClipping使用時のポリゴン欠け</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/11/pv3d21-frustumclipping.html" />
    <id>http://www.morocoshi.net/blog/2009/11/pv3d21-frustumclipping.html</id>

    <published>2009-11-09</published>
    <updated>2009-11-09</updated>

    <summary>renderer.clipping = new FrustumClipping(...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="Papervision3D" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[renderer.clipping = new FrustumClipping(～);<br />とかやっていると、<br />カメラを高速で回転した時とかに画面の端でポリゴンが<br />一瞬カリングされてしまう謎の現象があったんだけど<br /><a target="_blank" href="http://ferv.jp/blog/2009/06/04/frustumclipping_camera3dtarget/">jp.ferv.blogさんの記事</a>でやっと対処法がわかりました。<br /><br />FrustumClippingを使うときはCamera3D.targetは使わず<br />代わりにCamera.lockAt()を使えば解決するようです。<br /><br />で、これでめでたしめでたしと思いきや何故か上手くいかなくて、<br />結構長い間フガフガしてたんだけど<br />BasicViewクラスを使う時に<br /><b>new BasicView(640, 480, false, false);</b><br />って第五引数を省略してたせいで<br />カメラタイプがデフォルトの"Target"になってしまってて<br />コンストラクタで<b>camera.target = DisplayObject3D.ZERO;</b>されてたのが原因だった。。<br />いつも省略してたから全然気付かなかったよ・・・<br /><br /><b>new BasicView(640, 480, false, false, CameraType.FREE);</b><br />こんな風に第五引数を"Free"にして解決。<br />]]>
        
    </content>
</entry>

<entry>
    <title>PV3D2.1: レンズフレア</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/10/pv3d21.html" />
    <id>http://www.morocoshi.net/blog/2009/10/pv3d21.html</id>

    <published>2009-10-26</published>
    <updated>2009-10-26</updated>

    <summary>Papervision3Dでウォークスルーの実験中。レンズフレアエフェクトをつけ...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="PV3Dでウォークスルー" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Papervision3D" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[Papervision3Dでウォークスルーの実験中。<br /><a href="http://www.morocoshi.net/blog/material/swf/walk5/walkthrough5.swf" onclick="javascript:openswf(this.href, 600, 400, 9); return false;" target="_blank" class="openswf"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="walkthrough5.jpg" src="http://www.morocoshi.net/blog/material/img/walkthrough5.jpg" class="mt-image-none" style="" width="400" height="261" /></span></a><br />レンズフレアエフェクトをつけてみました。<br />海面のウネウネはなんか失敗。キラキラさせたかったんだけど・・・<br /><br />太陽の部分は3dsMaxのレンズエフェクトでレンダリングしたもので、<br />画面全体にかかる光の輪はFlashの放射グラデーションです。<br />レンズフレアの仕組みはよくわかってないんだけど、<br />光の輪が複数個あって、それが画面中央の座標と光源を結ぶ直線上に並んでるって<br />イメージはあったのでそんな感じで表現してます。

]]>
        <![CDATA[<br /><h3>太陽のスクリーン座標</h3>3D空間内にあるオブジェクトの基点の2D画面上での位置は<br />DisplayObject3D.screenで調べられるのでそれを使ってます。<br />
<pre class="brush: as3;">	sun = new DisplayObject3D();
	scene.addChild(sun);
	sun.autoCalcScreenCoords = true;
	sun.position = new Number3D(100000, 20000, 0);
</pre>
まず太陽の位置を知るためにダミーのDisplayObject3Dを生成して、シーンに追加しておきます。<br />autoCalcScreenCoords=trueしているのは<br />シーンがレンダリングされる度に自動でスクリーン座標を計算させる為です。<br /><br />後は毎フレームスクリーン座標を調べてその位置に太陽の画像を移動させるだけ。<br />毎フレーム実行しているコードはこんな感じ。<br />
<pre class="brush: as3;">	//sunMc, ring1Mc, ring2Mcはそれぞれ太陽と光の輪のムービークリップ
	var viewRect:Rectangle = new Rectangle(0, 0, viewport.width, viewport.height);
	var centerX:Number = viewport.width/2;
	var centerY:Number = viewport.height/2;
	var isShow:Boolean = (sun.screen.z &gt; 0 &amp;&amp; viewRect.contains(sun.screen.x + centerX, sun.screen.y + centerY));
	sunMc.visible = isShow;
	ring1Mc.visible = isShow;
	ring2Mc.visible = isShow;
	if (isShow) {
		sunMc.x = sun.screen.x + centerX;
		sunMc.y = sun.screen.y + centerY;
		ring1Mc.x = sun.screen.x * 0.5 + centerX;
		ring1Mc.y = sun.screen.y * 0.5 + centerY;
		ring2Mc.x = sun.screen.x * -1.0 + centerX;
		ring2Mc.y = sun.screen.y * -1.0 + centerY;
	}
</pre>
ここではsun.screenが太陽の画面上でのスクリーン座標になります。<br />screen.xとscreen.yがビューポートの真ん中を(0, 0)としたスクリーン座標で<br />screen.zはオブジェクトのカメラからの距離・・・だと思う。<br />カメラの前に太陽があるのか、後ろにあるのかを判定するのにscreen.zを使ってます。<br />もしscreen.z&lt;0だったらカメラの後ろにあるので表示を消すようにしてます。<br />（太陽がビューポートの矩形範囲外にあった時も消してます）<br />ちなみにscreenプロパティはシーンをレンダリングした後でアクセスしないと最新の座標が取れないようです。<br /><br /><h3>太陽を遮るオブジェクトの判定</h3>レンズフレアが画面内にあっても、それを遮るオブジェクトがあったら消す必要があります。<br />以前Shockwave3D時代にやっていた方法は、<br />カメラの位置から太陽の方向にレイを飛ばして地形モデルと交差したかどうかで判定していたんだけど<br />交差判定が重くなりそうだったので今回は別の方法にしてみました。<br /><br />まずビューポートに移っている映像で背景部分を黒くそれ以外を赤くした状態にして、<br />その画像から太陽の座標の色情報をBitmapData.getPixel()で調べて<br />赤い成分の割合で太陽の位置に遮蔽物があるかどうかを判定してます。<br /><br />↓赤と黒に分けるのはこんな流れでやってます。<br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="lensflare1.jpg" src="http://www.morocoshi.net/blog/material/img/lensflare1.jpg" class="mt-image-none" style="" width="630" height="361" /></span><br /><br /><div>今回シーンの背景が透過している画像を取得する為に<br />レンダリング結果を表示するビューポートにBitmapViewport3Dクラスを使ってみました。<br />普段Viewport3Dクラスを使う所を、BitmapViewport3Dに変えただけです。<br />BitmapViewport3Dを使うとBitmapViewport3D.bitmapDataにアクセスして<br />ビューポートに映っている画像がそのままBitmapDataとして拾えます。<br /><br />図のやり方で赤黒画像が出来上がるので、太陽の座標の色情報から赤成分を調べて、<br />0だったら太陽を表示する、255だったら表示しないという感じです。<br /><br />ちなみに赤黒画像をBlurFilterでぼかしているのは、<br />太陽が半分隠れていた時にレンズフレアが弱まる感じを表現したかったので<br />画像をぼかして空と遮蔽物の境界部分で赤色成分が徐々に変化するようにしてます。<br /><br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="lensflare2.jpg" src="http://www.morocoshi.net/blog/material/img/lensflare2.jpg" class="mt-image-none" style="" width="500" height="115" /></span></div>
<br />
遮蔽物判定部分のコードは抜粋になっちゃうけど以下のような感じです。<br />・はじめに用意しておくもの
<pre class="brush: as3;">	//BitmapViewport3Dオブジェクトを生成（第4引数をtrueにして背景を透過させる）
	viewport = new BitmapViewport3D(600, 400, false, true, 0x000000);
	//遮蔽物判定用のBitmapDataを生成（ビューポートと同じ大きさ）
	bmp = new BitmapData(viewport.width, viewport.height, false);
	bmp.lock();
</pre>
・以下のコードは毎フレーム、シーンのレンダリング直後に実行。
<pre class="brush: as3;">	//遮蔽物判定用BitmapDataを黒で塗り潰す
	bmp.fillRect(bmp.rect, 0xFF000000);
	//シーン画像のアルファチャンネルを赤チャンネルへコピー
	bmp.copyChannel(viewport.bitmapData, bmp.rect, new Point(), 8, 1);
	//全体をぼかす
	bmp.applyFilter(bmp, bmp.rect, new Point(), new BlurFilter(4, 4, 1));
	//最後に赤色成分の割合を取得(※px, pyは太陽の2D画面上でのXY座標です)
	var per:Number = (bmp.getPixel(px, py)  &gt;&gt; 16 &amp; 0xFF) / 255;
</pre>
<br />最後のperが赤成分の割合（0～1）なので、<br />これを使って太陽のスケールと光の輪のアルファをいじくってます。<br />ちなみに最後の行の「RGBカラー値 &gt;&gt; 16 &amp; 0xFF」のビット演算で赤成分の値を取ってます。<br />
それにしてもBitmapDataの処理ってAS3になっても相変わらず重いね・・・
<br />交差判定よりマシとはいえ毎フレームぼかしたりで結構重くなってしまった。。]]>
    </content>
</entry>

<entry>
    <title>PV3D2.1: 背景と高さ判定</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/10/pv3d21-7.html" />
    <id>http://www.morocoshi.net/blog/2009/10/pv3d21-7.html</id>

    <published>2009-10-17</published>
    <updated>2009-10-17</updated>

    <summary>Papervision3Dでウォークスルーの実験中。 背景をつけてみました。大き...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="PV3Dでウォークスルー" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Papervision3D" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="pv3d21920" label="PV3D2.1.920" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[Papervision3Dでウォークスルーの実験中。<br /><a href="http://www.morocoshi.net/blog/material/swf/walk4/walkthrough4.swf" onclick="javascript:openswf(this.href, 600, 400, 9); return false;" target="_blank" class="openswf"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="walkthrough4.jpg" src="http://www.morocoshi.net/blog/material/img/walkthrough4.jpg" class="mt-image-none" style="" width="400" height="244" /></span></a><a href="http://www.morocoshi.net/blog/material/swf/walk3/walkthrough3.swf" onclick="javascript:openswf(this.href, 600, 400, 9); return false;" target="_blank" class="openswf"> <br /></a>背景をつけてみました。<br />大きい一枚の画像をカメラの角度に合わせて上下左右にスクロールさせてます。<br />あと、高さ判定処理を組みなおして少しそれっぽく動けるようにしました。<br />高い所のモデルの下をくぐったり、高い所から落ちたりできます。<br /><br /><h3>背景の追加<br /></h3><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="walk4sky.jpg" src="http://www.morocoshi.net/blog/material/img/walk4sky.jpg" class="mt-image-none" style="" width="600" height="100" /></span><br />背景に使った空画像の全体図はこんな感じ。<br />手前のくっきりしてる雲だけ<a target="_blank" href="http://www.planetside.co.uk/content/view/15/27/">Terragen2</a>でレンダリング・・・というか知らない間に2出てたんだね。<br />
カメラは横に0～360°しか動かないのでその角度と画像のX座標をリンクさせているだけです。<br />実際は端が切れないように画像を横方向に多めにループさせてます。<br />横方向は簡単だったんですが、縦方向がカメラから水平線の位置を割り出す必要があって、<br />今はまだ目分量による簡単な位置合わせしかしていないので正確ではないです。<br /><br />ちゃんとした水平線の高さの割り出し方を調べるのがベストだと思うんだけど、<br />物凄い遠くに配置したダミーのDisplayObject3Dが常にカメラの正面(高さは海面)にくるようにして<br />そのダミーオブジェクトの座標を調べるって方法でもいける気がします。試してないけど・・・<br />Papervision3DではDisplayObject3D.autoCalcScreenCoords = trueしてから<br />DisplayObject3D.screenを調べれば基点のスクリーン座標が簡単に調べられるようです。<br /><br /><h3>高さの判定</h3>今までは単純にキャラ上空から真下に飛ばしたレイと地形モデルの最初の交点にキャラを移動させていただけで<br />モデルの下をくぐったりできなかったんですが、<br />今回は交差する全ての点の中から次に進める高さを調べているのでそれっぽく動けるようになりました。<br />(斜面を滑り落ちるような処理は高さ判定の処理とは別物です)<br />やっている事はだいたいこんな感じです。<br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="heightcheck.png" src="http://www.morocoshi.net/blog/material/img/heightcheck.png" class="mt-image-none" style="" width="422" height="518" /></span><br />基本的にキャラクターの移動前の高さと移動後の高さを比べて<br />先に進めるか進めないかの判定くらいしかしていません。<br />先に進めなかったら移動前の位置に戻しています。<br />高さ判定のコードがそれ以外の処理に混ざってしまっているのでコードは割愛しますが<br />内容はほとんど上の図そのままです。if文だらけになるのはしょうがないのかな。。<br />こんなに条件が多くなってしまったのは高いところから落下する処理があった為で、<br />常に足が地面に接地しているだけなら<br /><ul><li>一番近い高さに移動させる</li><li>高さが違いすぎたら元に戻す</li></ul>この処理だけでもなんとかなりそうな気がします。<br /><br />
条件分岐が多いとはいえ交差判定は今まで通り1回だけで済んでいるので<br />
処理はたいして重くならずに済みました。<br />
ただ高さだけで判定していて正面に壁があるかどうかはまったく調べていないので、<br />
ゲームでよくある壁に沿って滑るような動きができないし、<br />
キャラクタ―が壁に半分めり込んだりします。<br />複雑な地形での壁の判定はどうしようかな・・・<br />]]>
        
    </content>
</entry>

<entry>
    <title>なんだかMovableTypeの調子がおかしい</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/10/movabletype.html" />
    <id>http://www.morocoshi.net/blog/2009/10/movabletype.html</id>

    <published>2009-10-07</published>
    <updated>2009-10-07</updated>

    <summary>過去の記事を見直してたら追記したはずのテキストがいつのまにかごっそり抜けてた。キ...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="Blog" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[過去の記事を見直してたら追記したはずのテキストがいつのまにかごっそり抜けてた。<br />キャッシュから修正しておいたけど、なんだったんだろう。。<br />再構築した時になんかおかしくなっちゃったのかな･･･<br /><br />あと最近<a target="_blank" href="http://alternativaplatform.com/en/alternativa3d/">Alternativa3D</a>を勉強しようか迷ってます。<br />作りこんでくるとどうしてもPapervision3Dは表現的な制約が多くて。。<br />かといってAlternativa3Dは国内の記事が少なくて行き詰った時に大変そうだし、<br />頑張って使えるようになった後にPapervision3Dがバージョンアップしたら虚しいし。<br />とりあえずクリッピングといい感じのポリゴンソート(っていうの？)とテクスチャの歪み補正が<br />常に使える状態になってくれれば幸せになれそうなんだけどなあ。ふがふが。<br /> ]]>
        
    </content>
</entry>

<entry>
    <title>PV3D2.1: 水の流れの表現</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/10/pv3d-2.html" />
    <id>http://www.morocoshi.net/blog/2009/10/pv3d-2.html</id>

    <published>2009-10-07</published>
    <updated>2009-10-07</updated>

    <summary>前回のエントリーの続きです。滝と川を作ったんですがそのアニメーションのさせ方なん...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="PV3Dでウォークスルー" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Papervision3D" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="pv3d21920" label="PV3D2.1.920" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[<a href="http://www.morocoshi.net/blog/2009/10/pv3d-1.html">前回のエントリー</a>の続きです。<br />滝と川を作ったんですがそのアニメーションのさせ方なんかをメモしておきます。<br /><br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="walk3takitsubo.jpg" src="http://www.morocoshi.net/blog/material/img/walk3takitsubo.jpg" class="mt-image-none" style="" width="410" height="281" /></span><br />]]>
        <![CDATA[<div>滝つぼの所は特に変わったことはしてません。<br />普通に水が広がるアニメーションのムービークリップを作って、<br />それをMovieMaterialにして貼っているだけです。
<pre class="brush: as3;">new MovieMaterial(MovieClip参照, false, true, false, new Rectangle(0, 0, 256, 256));
</pre>
MovieMaterialは↑こんな感じに最後の引数で大きさを指定しておかないと<br />ムービークリップ全体の矩形サイズが変化してしまうようなアニメーションだった時に<br />マテリアルがずれてしまうようです。<br />またアニメーションさせる場合は第3引数をtrueにしないと<br />マテリアルが更新されずに止まったままになってしまいます。<br /><br />あと仕組みを理解してるわけではないんだけど、<br />このマテリアルを毎フレーム更新する処理って結構重いんじゃないかなって思いました。<br />滝つぼは常に動いちゃってるのでしょうがないけど、<br />たまにしか見た目が変化しないアニメーションの場合は<br />第3引数をfalseにしておいて、見た目が変化するタイミングで<br />MovieMaterialクラスのdrawBitmap()を呼び出して<br />手動でテクスチャを更新した方がいいのかもしれません。<br /><br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="walk3water.jpg" src="http://www.morocoshi.net/blog/material/img/walk3water.jpg" class="mt-image-none" style="" width="578" height="210" /></span><br /></div>川と滝の流れですが、こっちはMovieMaterialを使いませんでした。<br />テクスチャが一定方向にスクロールしているだけだったので<br />ポリゴンのUV値を弄ってマッピング座標をずらす事でアニメーションさせています。<br /><br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="water.jpg" src="http://www.morocoshi.net/blog/material/img/water.jpg" class="mt-image-none" style="" width="128" height="128" /></span><br />川のテクスチャ<br /><br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="uvmap.jpg" src="http://www.morocoshi.net/blog/material/img/uvmap.jpg" class="mt-image-none" style="" width="400" height="273" /></span><br />maxで編集中の川のポリゴンのUV座標はこんな感じになってます。<br />全てのポリゴンでU軸が川に対して横方向、V軸が縦方向になるようにしてます。<br />これでV軸方向にUV値を変化させれば川のラインに沿って流れるようになるはず。<br /><br />そして最初に作ったUV値を毎フレーム変化させるスクリプトがこれです。<br />TriangleMesh3Dオブジェクトが持っている全Triangle3Dオブジェクトの3つの頂点のUV値を弄っています。<br />
<pre class="brush: as3;">//meshはTriangleMesh3Dオブジェクトです
for each(var face:Triangle3D in mesh.geometry.faces) {
	for each(var uv:NumberUV in face.uv) {
		uv.v -= 0.05;
	}
}
</pre>こんな感じでいけるかなーと思ったら何故か動かない･･･。<br />
しばらくハマってたんですがどこかで見つけた記事で(どの記事だったか忘れてしまった)<br /><br />「UV値を変更したらマテリアルとして使っているBitmapMaterialでresetMapping()をしないと見た目が変わらないよ」<br /><br />という情報を発見。<br />早速川のBitmapMaterialをuv値を動かした後にresetMapping()したらやっと動きました。<br /><br />しかししばらく流れる川を眺めていたら、今度は一定時間経過すると突然流れが止まってしまうトラブルが発生･･･。<br />これは未だにはっきりとした原因がまだわかっていないんですが、<br />どうもuv値が大きくなりすぎた時に表示がおかしくなってしまう気がします。<br />プラスだけじゃなくマイナス方向にスクロールさせても途中で止まります。<br />値が大きいといってもNumber型の限界を超えたとかそんなすごい数でもなく、<br />時間的に多分1000とかいってなかった気がする。<br /><br />で、色々模索して<br /><ul><li>UV値が大きくなりすぎなければいい</li><li>UV値が0～1の間に収まっていれば問題なさそう</li><li>じゃあuv0.v = (uv0.v + 0.1)%1;とかやれば解決？</li><li>でもこれやると3つのuv座標の位置関係が崩れてテクスチャが反転したりするから駄目</li><li>じゃあ3つのuv値それぞれの初期値+オフセット値として、オフセット値を0～1に収めればいい</li><li>それには全三角ポリゴンの全UV値を最初に保存しておく必要がある</li><li>しかもスライドさせる時にどのUV値がどの初期値なのか調べる必要もある</li></ul>という非常に面倒くさい方法に辿りつきました。<br />今思うとMovieMaterialでアニメーションさせればよかったかもしれない･･･。<br />その時に作ったクラスはこれです↓<br /><br />
<pre class="brush: as3;">package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.Dictionary;
	import org.papervision3d.core.geom.renderables.Triangle3D;
	import org.papervision3d.core.geom.TriangleMesh3D;
	import org.papervision3d.core.math.NumberUV;
	import org.papervision3d.materials.BitmapMaterial;
	/**
	 * ポリゴンのUV値をスライドさせてテクスチャを動かします。
	 * Papervision3D ver2.1.920で使えます。
	 */
	public class TextureSlider {
		private var faces:Dictionary;
		private var models:Dictionary;
		private var materials:Dictionary;
		private var sp:Sprite;
		//コンストラクタ
		public function TextureSlider() {
			sp = new Sprite();
			faces = new Dictionary();
			models = new Dictionary();
			materials = new Dictionary();
		}
		/**
		 * スライド対象のBitmapMaterialを登録します（登録しないとスライドしても見た目が変化しません）
		 * @param	bitmap
		 */
		public function addMaterial(bitmap:BitmapMaterial):void {
			materials[bitmap] = bitmap;
		}
		/**
		 * テクスチャをスライドさせるモデルを指定します
		 * @param	model	テクスチャをスライドさせたいモデル
		 * @param	speedU	1フレームで変化するU軸方向のスライド値
		 * @param	speedV	1フレームで変化するV軸方向のスライド値
		 */
		public function addModel(model:TriangleMesh3D, speedU:Number, speedV:Number):void {
			if (models[model] != null) return;
			models[model] = { slideU:0, slideV:0, speedU:speedU, speedV:speedV, target:model };
			for each(var face:Triangle3D in model.geometry.faces) faces[face] = { uvs:[face.uv0.clone(), face.uv1.clone(), face.uv2.clone()] };
		}
		/**
		 * 登録情報破棄＆スライド停止
		 */
		public function dispose():void {
			faces = new Dictionary();
			models = new Dictionary();
			materials = new Dictionary();
			stopSlide();
		}
		/**
		 * スライド開始
		 */
		public function startSlide():void {
			sp.addEventListener(Event.ENTER_FRAME, onEnter);
		}
		/**
		 * スライドを停止
		 */
		public function stopSlide():void {
			sp.removeEventListener(Event.ENTER_FRAME, onEnter);
		}
		/**
		 * 1回スライドさせる
		 */
		public function stepSlide():void {
			for each(var m:Object in models) {
				m.slideU = (m.slideU + m.speedU) % 1;
				m.slideV = (m.slideV + m.speedV) % 1;
				for each(var face:Triangle3D in m.target.geometry.faces) {
					var fdata:Object = faces[face];
					for (var i:int = 0; i &lt;= 2; i++ ) {
						face.uv[i].u = fdata.uvs[i].u + m.slideU;
						face.uv[i].v = fdata.uvs[i].v + m.slideV;
					}
				}
			}
			for each(var bm:BitmapMaterial in materials) if (bm != null) bm.resetMapping();
		}
		//毎フレーム処理
		private function onEnter(e:Event):void {
			stepSlide();
		}
	}	
}
</pre><br />
使い方は以下のような感じで。<br /><br />
<pre class="brush: as3;">//plane1とplane2がマテリアルをスライドさせたいモデル
//map1とmap2がモデルに貼ってあるBitmapMaterial
var slider:TextureSlider = new TextureSlider();
slider.addModel(plane1, 0, 0.02);
slider.addModel(plane2, 0, 0.02);
slider.addMaterial(map1);
slider.addMaterial(map2);
slider.startSlide();
</pre>

負荷は検証していないので
どのくらいのポリゴン数まで耐えられるかちょっとわかりません。<br />常に一定速度で動くものにしか対応できないので
もっと汎用性をもたせた設計にすればよかったかも。<div><br /></div>]]>
    </content>
</entry>

<entry>
    <title>PV3D2.1: ステージできた＆色々困った事</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/10/pv3d-1.html" />
    <id>http://www.morocoshi.net/blog/2009/10/pv3d-1.html</id>

    <published>2009-10-05</published>
    <updated>2009-10-05</updated>

    <summary>Papervision3Dでウォークスルーの実験中。今回は島を作ってテクスチャ貼...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="PV3Dでウォークスルー" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Papervision3D" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="pv3d21920" label="PV3D2.1.920" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[Papervision3Dでウォークスルーの実験中。<br />今回は島を作ってテクスチャ貼ってみたよ。<br />足元の高さ判定の処理はまだちゃんと組んでないので<br />穴が開いた地形の下もくぐれないし、高い所から落ちると一瞬で着地します。<br /><br /><a href="http://www.morocoshi.net/blog/material/swf/walk3/walkthrough3.swf" onclick="javascript:openswf(this.href, 600, 400, 9); return false;" target="_blank" class="openswf"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="walkthrough3.jpg" src="http://www.morocoshi.net/blog/material/img/walkthrough3.jpg" class="mt-image-none" style="" width="360" height="297" /></span></a><div><b>矢印キー：移動<br />SHIFT+矢印キー：カメラ回転<br />F：FPSの限界切り替え<br />W：ワイヤーフレームON/OFF<br />M：テクスチャの歪み補正ON/OFF<br />1～4：レンダラ切り替え(デフォルトは1)</b><br /><b>PAGE UP：カメラズームイン<br />PAGE DOWN：カメラズームアウト<br />HOME：カメラズームリセット<br /></b><br /></div>]]>
        <![CDATA[<h3>島のモデリング</h3><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="walk3max.jpg" src="http://www.morocoshi.net/blog/material/img/walk3max.jpg" class="mt-image-none" style="" width="350" height="249" /></span><br /><div>島は3dsMaxでモデリング。全部で689△ポリゴンです。<br />Shockwave3Dだったらキャラクター1体に使えるポリ数だね･･･<br />ポリゴンはもっと減らすこともできたんだけど<br />ポリゴン大きいとデフォルトのレンダラでテクスチャの歪みとポリゴン欠けが激しいから<br />平坦な部分も分割しちゃってます。それでもカメラが近いと歪んじゃうけど。<br /><br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="walk3pv.jpg" src="http://www.morocoshi.net/blog/material/img/walk3pv.jpg" class="mt-image-none" style="" width="350" height="234" /></span><br /></div><div>Papervision3Dで表示するとこんな感じ。<br />Shaderマテリアルとかは速度を優先して使いませんでした。<br />バンプマップとか使いたかったな。<br /><br /><h3>DAEデータからモデルを探す時にはまった事</h3>そういえば、今回collada(dae)モデル内に複数のモデルが混在していて、<br />DAEデータ内にある各メッシュモデル(TriangleMesh3D)を探す必要があったんですよ。<br />今まではmax内でつけたモデル名がそのままIDとして使われていて、<br />DAEファイルを覗かなくても<br /><pre class="brush: as3;">var mesh:TriangleMesh3D = dae.getChildByName("maxでつけたモデル名", true) as TriangleMesh3D;</pre>こうするだけで特定のモデルを探す事ができていたのに今回は何故かうまくいかず。<br />DAE内部の構成がどうなってるのか気になってトレースするスクリプトを作ってみました。<br />
<pre class="brush: as3;">import flash.utils.describeType;
import org.papervision3d.core.proto.DisplayObjectContainer3D;
import org.papervision3d.objects.DisplayObject3D;
public function getObjectTree(obj:DisplayObjectContainer3D):String {
	return scanObjectTree(obj, [], 0);
}
private function scanObjectTree(obj:DisplayObjectContainer3D, indents:Array, lv:int = 0):String {
	var str:String = "";
	var line:String = (lv == 0)? "" : indents.map(function(d:int, i:int, a:Array):String { return (i&gt;=1 &amp;&amp; i &lt; lv)? ["　│", "　　"][d] : "" } ).join("") + ["　├", "　└"][indents[lv]];
	var className:String = describeType(obj).@name.split("::")[1];
	var mark:String = (className == "DisplayObject3D")? "" : "*";
	var disp:DisplayObject3D = obj as DisplayObject3D;
	if (disp != null) {
		str = line + "&lt;" + disp.name +"&gt;(" +mark + className + ") [" + String(disp.position) + "]\n";
	} else {
		str = line + "(" + className + ")\n";
	}
	var count:int = 0;
	for each(var d:DisplayObject3D in obj.children) {
		indents[lv + 1] = (++count == obj.numChildren)? 1 : 0;
		str += scanObjectTree(d, indents, lv+1);
	}
	return str;
}
</pre>
DAEファイルのロードが完了した後に<br /><pre class="brush: as3;">trace(getObjectTree(調べたいDAEオブジェクト));</pre>ってやると、↓こんな感じにトレースしてくれます。フォントによっては線がずれるかも。<br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="tracetree.png" src="http://www.morocoshi.net/blog/material/img/tracetree.png" class="mt-image-none" style="" width="350" height="173" /></span><br />データは&lt;名前&gt;(クラス名)[座標]の並びになってます。<br />*はDisplayObject3D以外につきます。見分けやすくする為のただのマークです。<br />で、赤線部分のTriangleMesh3Dクラスのオブジェクトが今回必要だったメッシュモデルなんですが･･･<br />maxでつけた名前は「field」「river」「waterfall」です。<br />でも実際はその1つ下に見覚えのない数字のノードができていて、そっちがメッシュモデルになってしまっています。<br />原因はわからないけど、とにかくここの&lt;名前&gt;でアクセスすればメッシュモデルが取得できるんで、<br /><pre class="brush: as3;">dae.getChildByName("43", true);//field取得
dae.getChildByName("47", true);//river取得
dae.getChildByName("49", true);//waterfall取得
</pre>これで一件落着かなって思ってました。<br />実際これでテストしたらうまくいってしまったので問題ないと思っていたんですが･･･<br />この&lt;数字&gt;と表示されている部分、DAEファイルを覗いてみるとそもそも数字がIDになったノードなんて見当たりません。<br />おかしいなーと思って該当するメッシュモデルのノードを見ると、名前もIDもついてない。。<br />つまりこれは、IDが設定されていないノードに勝手に名前がつけられていただけで、<br />43とか47とかはたまたまその数字になっていただけって事･･･？<br />何度かテストするとモデルが取得できない事があってその時は数字が違っていたので<br />ここの名前でアクセスするのはまずい事がわかりました。<br />これ気づくのにえらい時間かかった。。<br /><br />自分の環境ではmaxでつけたモデル名のノードの中にメッシュモデル(TriangleMesh3D)があるのは確実だったので、<br />DisplayObject3Dが内包している全てのTriangleMesh3Dクラスをリストアップするスクリプトを作って解決しました。<br />
<pre class="brush: as3;">import org.papervision3d.objects.DisplayObject3D;
public static function getTriangleMeshList(obj:DisplayObject3D):Array {
	var list:Array = new Array();
	for each(var d:DisplayObject3D in obj.children) {
		var childs:Array = getTriangleMeshList(d);
		if (childs.length == 0) {
			if (describeType(d).@name.split("::")[1] == "TriangleMesh3D") list.push(d);
		} else {
			list = list.concat(childs);
		}
	}
	return list;
}
</pre>

引数にDisplayObject3Dを渡すとTriangleMesh3Dを配列で返してくれます。<br />実際はこんな感じに使います↓<br />
<pre class="brush: as3;">//まずモデル名でDisplayObject3Dを取得
var node:DisplayObject3D = dae.getChildByName("モデル名", true);
//その中にあるTriangleMesh3Dを抽出
var field:TriangleMesh3D = getTriangleMeshList(node)[0];
</pre>これでやっと目的のモデルが取れるようになりました。ふー。<br />今回はこれで解決したとはいえ、そもそもなんでIDなしのノードが<br />余計に作られるようになったのかが謎のままだし<br />根本的な解決にはなってないけどね。。<br /><br /><h3>テクスチャの歪み補正</h3>あと今回色々と重さの比較をしようと思って<br />テクスチャの歪み補正とレンダラを切り替えられるようにしてあります。<br />テクスチャの歪み補正は、BitmapMaterialを生成する時に<br />
<pre class="brush: as3;">var mat:BitmapMaterial = new BitmapMaterial(bitmapData, true);</pre>こんな感じに第2引数をtrueにしたり、<br />
<pre class="brush: as3;">mat.precise = true;</pre>
BitmapMaterialオブジェクトのpreciseプロパティをtrueにする事で設定できます。<br /><br />
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="compareprecise.jpg" src="http://www.morocoshi.net/blog/material/img/compareprecise.jpg" class="mt-image-none" style="" width="450" height="157" /></span><br />左がデフォルトの補正無し。カメラに近いところがなんか伸びちゃってるね。<br />早速補正有りを試してみたところ･･･なんかものすっごい分割されてる。。<br />てっきりいつもよりちょっと重い処理でテクスチャ描画する程度かなーって考えてたけど<br />こんなに分割されるんじゃローポリにした意味がない気がするよ。。<br />ただ、この分割で増えたポリゴンが全ての処理で使われるわけではないようで、<br />実際こんなに細切れになってもポリゴンの欠け方が補正無しの時と同じでした。<br />細かくなった分欠けにくくなるわけでもないらしい。うーん<br />当然分割数に応じて重くなるんだけど、この分割数がカメラの位置にかなり影響されるんで<br />モデルが沢山見えても軽い時もあればポリゴン数枚で激重になる事もありました。<br />ウォークスルー系コンテンツでは使いどころが難しい･･･。<br /><br /><h3>レンダラの比較</h3><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="comparerenderer.jpg" src="http://www.morocoshi.net/blog/material/img/comparerenderer.jpg" class="mt-image-none" style="" width="500" height="239" /></span><br />こっちはレンダラの切り替えテスト。<br />デフォルトのBasicRenderは軽い代わりにポリゴン欠けが酷い(左)<br />ので、QuadrantRenderEngineという高機能レンダラに切り替えてみました(右)<br />QuadrantRenderEngineに関しては<a target="_blank" href="http://blog.r3c7.net/?p=233">note.xさんの記事</a>でお勉強しました。<br /><br />何種類か試したところ、地面に足が潜り込まないようにするだけなら<br /><pre class="brush: as3;">renderer = new QuadrantRenderEngine(QuadrantRenderEngine.CORRECT_Z_FILTER);</pre>だけでいける気がします。<br />交差したポリゴンを分割してくれるフィルタ(QUAD_SPLIT_FILTER)もあるんだけど<br />テクスチャの歪み補正と併用しないと分割時にテクスチャが断層みたいにずれて<br />しかもカメラが動くたびに再分割するのでピクピク動いてしまいます。<br />で、当然これ使うと重くなるんですが、問題なのは実は重さの件だけではなくて･･･<br />カメラが地面に近いところを動く事が多いので<br /><pre class="brush: as3;">renderer.clipping = new FrustumClipping(FrustumClipping.NEAR);</pre>でレンダラのclippingプロパティにFrustumClippingを設定して<br />手前のポリゴンが消えてしまうのを防いでいるんですが、<br />何故かQuadrantRenderEngineとFrustumClippingを組み合わせると<br />エラーを吐いてFlashが止まってしまう。。<br />FrustumClippingがQuadrantRenderEngineでは使えないものなのか、それとも設定方法が悪いのか･･･<br />原因はわからなかったんですが、どうしようもなかったので<br />サンプルではBasicRender以外クリッピングを無効のままにしてあります。<br />結局、足元のポリゴン欠けが解消しても手前のポリゴンが消えるという事態に。<br />クリッピングのやり方が分かるまではこれも使うの難しいな･･･。<br /><br />ウーンなんか長くなっちゃったね。<br />水の表現に関してはエントリー分けておきます。<br /><a href="http://www.morocoshi.net/blog/2009/10/pv3d-2.html">PV3D: 水の流れの表現</a><br /></div>]]>
    </content>
</entry>

<entry>
    <title>PV3D2.1: 交差判定高速化</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/09/pv3d.html" />
    <id>http://www.morocoshi.net/blog/2009/09/pv3d.html</id>

    <published>2009-09-27</published>
    <updated>2009-09-27</updated>

    <summary>視線とメッシュの交差判定を高速化してみました。サンプルのポリゴン数は前回と同じに...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="PV3Dでウォークスルー" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Papervision3D" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="pv3d21920" label="PV3D2.1.920" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[<a href="http://www.morocoshi.net/blog/2009/09/post-3.html">視線とメッシュの交差判定</a>を高速化してみました。<br />サンプルのポリゴン数は前回と同じにしてあります。<br /><a href="http://www.morocoshi.net/blog/material/swf/walk2/walkthrough2.swf" onclick="javascript:openswf(this.href, 600, 400, 9); return false;" target="_blank" class="openswf"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="walkthrough2.jpg" src="http://www.morocoshi.net/blog/material/img/walkthrough2.jpg" class="mt-image-none" style="" width="240" height="248" /></span></a><br />矢印キー：移動<br />SHIFT+矢印キー：カメラ回転<br />右上MAPクリック：地形変形<br />FPSクリック：FPSの限界切り替え<br />]]>
        <![CDATA[<a href="http://www.morocoshi.net/blog/2009/09/pv3d--.html">前回</a>FPS30くらいだったんだけど今回60～70くらいまであがった！<br />(前回のサンプルではfps24以上あげられないけど)<br /><br />あと記事を若干加筆しました。コードは未だに検証中だけど・・・<br /><br /><h3>やってる事</h3><a href="http://www.morocoshi.net/blog/2009/09/post-3.html">視線と三角形の交差判定</a>が重かったので<br />今回AABBとの交差判定処理を混ぜています。<br />AABBというのはAxis Aligned Bounding Boxの略で, 辺がワールド空間のXYZ軸に並行な直方体の事だそうです。<br />ワールド空間における傾きの無いバウンディングボックスのようなものと考えればいいかも。<br /><br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="aabb.png" src="http://www.morocoshi.net/blog/material/img/aabb.png" class="mt-image-none" style="" width="366" height="242" /></span><br />前回は視線ベクトルと全三角形とを重い処理でひたすら交差判定していたんですが<br />図のように交差判定をする前にあらかじめ視線と全三角形をAABB化しておきます。<br />そして視線のAABBと各三角形のAABBとが交差しているかを最初にチェックして、<br />AABB同士交差しているものだけ絞りこむことで重い交差判定の回数を減らしています。<br />AABB同士の交差判定はかなり高速なのと、交差判定対象のメッシュが動かない場合は<br />全三角形をAABB化するのは最初の1回だけで済みます。<br />実際はAABB同士の交差判定で絞り込んだ後、<br />視線ベクトルの直線と三角形のAABBとの交差判定をしてさらに三角形を絞り込みます。<br /><br />ちなみに視線ベクトルが無限の長さを持ってる場合は視線がAABB化できないため<br />最初のAABB同士の交差判定はできないので<br />視線ベクトルの直線と三角形のAABBとの判定だけになります。<br /><br />具体的な手順はこんな感じ<br /><ol><li>三角ポリゴンを包むAABBを求める(動かないなら最初の1回だけ)</li><li>視線ベクトルが長さを持っていたら視線のAABBと1を交差判定⇒判定なしで交差なし</li><li>1のAABBと視線ベクトル(直線)を交差判定⇒判定なしで交差なし</li><li>最後は今まで通り視線と三角ポリゴンを交差判定</li></ol>AABBと直線の交差判定はこちらのサイトを参考にしています。<br /><a target="_blank" href="http://marupeke296.com/COL_3D_No18_LineAndAABB.html">その18 直線とAABB</a> - <a target="_blank" href="http://marupeke296.com/index.html">マルペケつくろーどっとコム</a><br /><br /><pre class="brush: as3;">/**
 * (※追記)ASのコードはもうすこし検証してから載せ直すことにしました。
 */
</pre>
<br /><h3>処理落ちの原因</h3>あと、<a href="http://www.morocoshi.net/blog/2009/09/pv3d--.html">前回のエントリー</a>のサンプルで<br />自分の環境では時々カメラがある角度を向くと<br />処理が突然重くなって最悪10秒近くフリーズする事があって困ってたんですが、<br />どうやら地形に使っているBitmapMaterialのスムージングをtrueにしていたのが原因みたいです。<br />スムージングONにしただけであそこまでフリーズするとは思えないけど･･･<br />実際OFFにしたら問題なく動かせるようになりました。うーん･･･<br />テクスチャは縦横100px程度だから、大きなモデルでスムージングかけたのがいけないのかな。<br />スムージングの他に別の要因が絡んでたのかもしれないけど。<br /><div><br /></div>]]>
    </content>
</entry>

<entry>
    <title>PV3D2.1: ウォークスルーテスト</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/09/pv3d--.html" />
    <id>http://www.morocoshi.net/blog/2009/09/pv3d--.html</id>

    <published>2009-09-26</published>
    <updated>2009-09-26</updated>

    <summary>以前のエントリの視線とメッシュの交差判定を使って凸凹の地形を歩かせてみました。 ...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="PV3Dでウォークスルー" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Papervision3D" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="pv3d21920" label="PV3D2.1.920" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[以前のエントリの<a href="http://www.morocoshi.net/blog/2009/09/post-3.html">視線とメッシュの交差判定</a>を使って<br />凸凹の地形を歩かせてみました。<br /><br />
<a href="http://www.morocoshi.net/blog/material/swf/walk1/walkthrough1.swf" onclick="javascript:openswf(this.href, 600, 400, 9); return false;" target="_blank" class="openswf"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="walkthrough1.jpg" src="http://www.morocoshi.net/blog/material/img/walkthrough1.jpg" class="mt-image-none" style="" width="235" height="209" /></span></a>
<div><ul><li>矢印キーで移動</li><li>右上のマップをクリックすると地形変形</li></ul></div>]]>
        <![CDATA[地形は10x10分割のPlaneをperlinNoiseした画像の明るさに合わせて頂点移動してるだけです。<br />
今回交差判定用のレイを2本飛ばしていて、<br />
1つはキャラクタ上空から真下に飛ばして地形の高度をチェックして、<br />
2つ目はカメラの注視点から視点にむかってレイを飛ばして<br />
カメラがポリゴンに埋まっていないかをチェックしています。<br />
(地形との交差点までの距離がカメラの距離より短かったら埋まっている)<br />
<br /><h3>キャラクターモデル</h3>
ロボットは3dsMax2010で作ってColladaエクスポータで書き出したものです。<br />エクスポータは<b><a target="_blank" href="http://opencollada.org/download.html">ここ</a></b>の「OpenCOLLADA for 3ds Max(ver1.2.3)」を使いました。<br /><br />顔のディスプレイっぽいところ、黒い板の向こうに光る顔が見えてますが<br />透過させてるわけではなくて、法線フリップした黒ボックスを組み合わせてます。<br />↓こんな感じ<br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="robot.jpg" src="http://www.morocoshi.net/blog/material/img/robot.jpg" class="mt-image-none" style="" width="400" height="243" /></span><br /><br /><h3>Colladaファイルの書き出し</h3>モデルができたらエクスポータで書き出すだけなんだけど、<br />テクスチャ付きのColladaモデルをPapervisionで表示するまで<br />いくつかハマったポイントがあったのでメモしておきます。<br /><ul><li>書き出し形式<br /></li></ul><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="collada1.jpg" src="http://www.morocoshi.net/blog/material/img/collada1.jpg" class="mt-image-none" style="" width="385" height="144" /></span><br />Autodesk Colladaじゃなくて下のCOLLADA NextGenの方を選びます。<br />最初Autodeskの方を選んでて色々おかしな事になってました。。<br /><br /><ul><li>書き出しオプション<br /></li></ul><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="collada2.jpg" src="http://www.morocoshi.net/blog/material/img/collada2.jpg" class="mt-image-none" style="" width="413" height="281" /></span><br />細かいオプションはわからないけどとりあえずこんな感じでいけました。<br />Copy Imagesを選ぶとdaeファイルを書き出した所に画像データがコピーされるみたい。<br /><br /><ul><li>daeファイル内の個人情報</li></ul>daeファイルといっても中身はXMLなので普通に編集できます。<br />書き出したファイルを見ると上の方に&lt;contributor&gt;タグがあるんですが<br />この中にユーザー名とかmaxファイルのフルパスとか入っちゃってるので<br />まずそうなのは消しておいたほうがいいかも。<br /><br /><ul><li>サーバーにあげると画像マテリアルが表示できない</li></ul>
これなんだけど、単純にパスの参照がずれてるとか、<br />クロスドメインの問題かなと思ったんだけど、結局よくわからなかった･･･<br />DAEクラスのインスタンス生成時にマテリアルリストを渡す方法ではうまくいったので<br />今回はその方法でやっています。<br /><br />DAEのマテリアルリストの設定方法はこちらのサイトが詳しいです。<br /><a target="_blank" href="http://aaharu.blogspot.com/2009/06/pv3dpapervision3das30_18.html">[Pv3D]Papervision3Dをやってみた　その３[AS3.0]</a> - <a target="_blank" href="http://aaharu.blogspot.com/">明日の今日</a><br /><a target="_blank" href="http://aaharu.blogspot.com/2009/07/pv3dflexcolladadae.html">[Pv3D][Flex]Collada(.dae)のマテリアル張り替え</a> - <a target="_blank" href="http://aaharu.blogspot.com/">明日の今日</a><br /><br /><h3>キャラクターアニメーション</h3>あと、せっかくなのでアニメーションもさせてみました。<br />複数アニメーションに関してはこちらの記事を参考にさせてもらいました。<br />
<a target="_blank" href="http://www.kyucon.com/blog/2009/06/papervision3d-21-alpha-colladadae.html">[Papervision3D 2.1 alpha] Collada(.dae)で複数モーション</a> - <a href="http://kyucon.com/blog/" target="_blank">KYUCON*BLOG</a><br />Shockwave3Dの時は時間ベースの歩行アニメーションと<br />フレームベースの移動を同期させる為に<br />FPSを計算してアニメーションスピードを調節してたんだけど、<br />現状のDAEクラスにはアニメーションの再生倍率を弄る機能はついてないのかなあ。]]>
    </content>
</entry>

<entry>
    <title>キャラクターの物理演算</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/09/test.html" />
    <id>http://www.morocoshi.net/blog/2009/09/test.html</id>

    <published>2009-09-15</published>
    <updated>2009-09-15</updated>

    <summary>ブログのヘッダーで、人もドラッグで飛ばせるようにしたよ。建物の屋根にも当たり判定...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="Blog" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Box2D" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[ブログのヘッダーで、人もドラッグで飛ばせるようにしたよ。<br />建物の屋根にも当たり判定つけたので乗せたりできます。<br />ドラッグして初めて当たり判定が発生するんだけど<br />負荷軽減の為に一定時間止まってると元に戻っちゃうから<br />積みあげて遊ぶとかは難しいね･･･<br /><br />人の動きはBox2Dを使った物理演算での動きと<br />あらかじめ設定しておいたラインに沿った単純な動きを切り替えてます。<br /><br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="header4.png" src="http://www.morocoshi.net/blog/material/img/header4.png" class="mt-image-none" style="" width="478" height="139" /></span>
<br />Box2Dのデバッグ表示(ドラッグしたり足を踏み外した人だけ演算対象にしてます)<br /><br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="header5.png" src="http://www.morocoshi.net/blog/material/img/header5.png" class="mt-image-none" style="" width="478" height="139" /></span>
<br />通常の動きで使うライン(演算対象になっていない人はこのラインに沿って動く)<br /><br />Box2D楽しいな～。Papervisionがなかなか進まない・・・]]>
        
    </content>
</entry>

<entry>
    <title>ヘッダーにキャラクター追加</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/09/post-5.html" />
    <id>http://www.morocoshi.net/blog/2009/09/post-5.html</id>

    <published>2009-09-13</published>
    <updated>2009-09-13</updated>

    <summary>特にゲーム性はなくて、ワラワラしてるのを眺めるだけです。Box2DFlashAS...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="Blog" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Box2D" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Flash" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="header1.png" src="http://www.morocoshi.net/blog/material/img/header1.png" class="mt-image-none" style="" width="348" height="186" /></span><br />特にゲーム性はなくて、ワラワラしてるのを眺めるだけです。<br /><a target="_blank" href="http://box2dflash.sourceforge.net/">Box2DFlashAS3</a>の勉強も兼ねて車を物理演算させてみたよ。<br />つまんで放り投げたりできます。たまにしかこないけど･･･<br />キャラクターも飛ばしたかったけど、重そうなので考え中。。<br /><br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="header2.png" src="http://www.morocoshi.net/blog/material/img/header2.png" class="mt-image-none" style="" width="382" height="209" /></span><br />
あと特に意味はないけど、一人一人にパラメータ持たせてみました。<br />クリックすると色々見れます。<br />メーターは左から、イライラ・疲労・トイレ・空腹<br />]]>
        
    </content>
</entry>

<entry>
    <title>ブログのデザイン変更</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/09/post-4.html" />
    <id>http://www.morocoshi.net/blog/2009/09/post-4.html</id>

    <published>2009-09-09</published>
    <updated>2009-09-09</updated>

    <summary>MobableType弄くりすぎておかしくなったから一からセットアップしなおし。...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="Blog" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[MobableType弄くりすぎておかしくなったから一からセットアップしなおし。。<br />ついでにドメインもとったのでタイトルも変えてみました。<br />デザインはまだ静止画だけどそのうちギミックとか仕込みたいな。<br />というか最初はヘッダー画像をぽちぽち描いてただけなんだけど、<br />サイドバーを地下フロアにした瞬間TheTowerみたくなってしまった･･･<br /><br />あとここ最近ネット浦島太郎状態で驚く事ばかりだったんですが、<br />数年ぶりに<a target="_blank" href="http://hyohyohyo.cool.ne.jp/">ヒョーゴノスケさんのサイト</a>に行ったら凄い作品が公開されてました！<br />KINPIRAってゲームなんだけどかなり面白いです。<br />楽しくてフィールドを黙々と更地にしてました。<br />ポリ数と描画クオリティ的に制限だらけのFlash3Dばかり弄ってたんで<br />こういうの見るとまたShockwave3Dやりたくなってしまう。。<br />もうlingoとか書き方忘れちゃったけどね･･･
                                    <br />]]>
        
    </content>
</entry>

<entry>
    <title>PV3D2.1: DisplayObject3D.worldの値が更新されるタイミング</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/09/displayobject3dtransform-1.html" />
    <id>http://www.morocoshi.net/blog/2009/09/displayobject3dtransform-1.html</id>

    <published>2009-09-06</published>
    <updated>2009-09-06</updated>

    <summary> 前回のエントリーで「DisplayObject3D.world」でモデルのワー...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="PV3Dでウォークスルー" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Papervision3D" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="pv3d21920" label="PV3D2.1.920" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[ <a href="http://www.morocoshi.net/blog/2009/09/post-3.html">前回のエントリー</a>で<br /><b>「DisplayObject3D.world」でモデルのワールド空間での<br />移動・回転・スケールの変換行列が取得できる</b><br />と書いたんですが、どうやらworldプロパティは<br />シーンがレンダリングされるタイミングで初めて値が更新されるみたいです。<br /><br />てことは、モデルを回転してからworldプロパティにアクセスしても<br />レンダリング直前では回転を適用する前の情報しか取れない事になる･･･<br />逆にレンダリングしてからアクセスしてしまうと、<br />例えば常に回転しているモデル上をキャラが歩く場合、<br />モデル回転→レンダリング→ワールド座標を取得して交差判定→キャラを動かす<br />という処理の流れになってしまって<br />キャラクターの描画が遅れる事になってしまう。。<br />かといって正確なworldプロパティを取得する為だけに<br />2回レンダリングするのも無駄すぎる･･･<br /><br />色々調べて、どーしてもいい方法が見つからなかったので<br />worldプロパティを使わずにワールド空間での変形情報(Matrix3D)を調べる事にしました。]]>
        <![CDATA[実は前回のエントリーで書いたDisplayObject3D.worldプロパティ、<br />最初このプロパティの存在に気づかずに<br />モデルのローカル空間？の変形情報が入っている<br /><b>DisplayObject3D.transform</b>プロパティ<br />を使ってworld相当の情報を無理矢理調べてました。<br /><br />
↓その時に作ったスクリプト<br />
<pre class="brush: as3;">import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.objects.DisplayObject3D;
/**
 * オブジェクトのワールド空間での変形情報を取得
 * @param	obj	
 * @return
 */
public static function getWorldTransform(obj:DisplayObject3D):Matrix3D {
	obj.updateTransform();
	var res:Matrix3D = new Matrix3D();
	res.copy(obj.transform);
	var parent3D:DisplayObject3D = obj.parent as DisplayObject3D;
	if (parent3D != null) res.calculateMultiply(getWorldTransform(parent3D), res);
	return res;
}
</pre>
引数にモデルを渡すと変形情報がMatrix3Dクラスで返ってきます。
<br />transformプロパティはあくまで自分の親からみた相対的な変形情報なので、<br />ワールド空間での最終的な変形情報を得るには<br />親のDisplayObject3Dを辿っていって、全ての親のtransformを混ぜる必要があります。<br />またtransformの値はDisplayObject3D.updateTransform()を実行しないと更新されません。<br />
yaw()、pitch()、roll()、localRotation～()、translate()、move～()を使ったり、レンダリングしたりすると<br />
自動でupdateTransform()が呼び出されるので必要ないみたいなんですが、<br />
それ以外の方法で動かす可能性もあるので一応呼び出すようにしてます。
<br />再帰処理があるのがちょっと嫌だけど、他に方法が思いつかない･･･

<br />とりあえず頂点座標をワールド座標に変換する処理とかで<br />worldを使わずにこの関数で調べたMatrix3Dを使えば大丈夫かなあ。]]>
    </content>
</entry>

<entry>
    <title>PV3D2.1: 視線とメッシュの交差判定</title>
    <link rel="alternate" type="text/html" href="http://www.morocoshi.net/blog/2009/09/post-3.html" />
    <id>http://www.morocoshi.net/blog/2009/09/post-3.html</id>

    <published>2009-09-05</published>
    <updated>2009-09-05</updated>

    <summary> Papervision3Dでウォークスルーをさせようと思ってます。キャラクター...</summary>
    <author>
        <name>てんちょ</name>
        <uri>http://www.morocoshi.net/blog/</uri>
    </author>
    
        <category term="PV3Dでウォークスルー" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Papervision3D" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="pv3d21920" label="PV3D2.1.920" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://www.morocoshi.net/blog/">
        <![CDATA[ Papervision3Dでウォークスルーをさせようと思ってます。<br />キャラクターが水平な地面を動くだけなら壁の判定だけすればいいんですが<br />凹凸のある地形に沿って動かしたいので<br />足元のポリゴンの高さを調べる必要があります。<br /><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="checkheight.png" src="http://freedom.s371.xrea.com/blog/material/img/checkheight.png" class="mt-image-none" style="" width="200" height="200" /></span><br /><br />Shockwave3DにはmodelsUnderRayっていう<br />レーザーを飛ばしてポリゴンに当たった座標が調べられる機能があったんで<br />Papervision3Dにもあるかなーって調べたけど見つかりませんでした。。<br />見つけられなかっただけで本当はあるのかもしれないけど、<br />諦めてmodelsUnderRay的な機能を作る事にしました。<br />やってることは、対象のメッシュモデルの全三角ポリゴンに対して、<br />視線と三角形が交差しているかひたすらチェックしていって、<br />交差しているものがあったら交差情報を返すという感じです。]]>
        <![CDATA[まず三角ポリゴンと視線が交差しているかチェックする処理ですが、<br />
<a target="_blank" href="http://www.t-pot.com/program/93_RayTraceTriangle/index.html">レイトレース：３角形と視線の交差判定</a><br />ここのサイトを参考にして組んでみました。<br />
<pre class="brush: as3;">import org.papervision3d.core.math.Number3D;
/**
 * レイが三角ポリゴンに当たっているかチェック(ポリゴンは頂点反時計周りで構成)
 * @param	pos	レイ放射開始地点
 * @param	vec	レイの方向
 * @param	p0	三角ポリゴンの頂点1
 * @param	p1	三角ポリゴンの頂点2
 * @param	p2	三角ポリゴンの頂点3
 * @param	isDoubleSided	裏向きのポリゴンも交差判定する
 * @return
 */
public function collideRayToTriangle(pos:Number3D, vec:Number3D, p0:Number3D, p1:Number3D, p2:Number3D, isDoubleSided:Boolean = false):Object {
	//レイの方向（正規化）
	var v:Number3D = vec.clone();
	v.normalize();
	//法線ベクトル
	var normal:Number3D = Number3D.cross(Number3D.sub(p1, p0), Number3D.sub(p2, p0));
	normal.normalize();
	var vn:Number = Number3D.dot(v, normal);
	//1.平面と平行なら交差なし(計算誤差を考慮)
	//2.片面チェックON時に視線と法線が同じ向き（裏側を見ている）なら交差なし
	if (Math.abs(vn) &lt; 0.0000001 || (vn &gt; 0 &amp;&amp; !isDoubleSided)) return null;
	var xpn:Number = Number3D.dot(Number3D.sub(pos, p0), normal);
	var distance:Number = -xpn / vn;
	//交差位置が視線と逆方向なら交差なし
	if (distance &lt; 0) return null;
	//視線と平面との交点
	var hit:Number3D = v.clone();
	hit.multiplyEq(distance);
	hit.plusEq(pos);
	//交点が三角形内にあるかチェック(計算誤差を考慮)
	var cross0:Number3D = Number3D.cross(Number3D.sub(hit, p0), Number3D.sub(p1, p0));
	if (Number3D.dot(cross0, normal) &gt; 0.000000001) return null;
	var cross1:Number3D = Number3D.cross(Number3D.sub(hit, p1), Number3D.sub(p2, p1));
	if (Number3D.dot(cross1, normal) &gt; 0.000000001) return null;
	var cross2:Number3D = Number3D.cross(Number3D.sub(hit, p2), Number3D.sub(p0, p2));
	if (Number3D.dot(cross2, normal) &gt; 0.000000001) return null;
	var res:Object = new Object();
	res.position = hit;
	res.distance = distance;
	return res;
}
</pre>
この関数に「レイを放射する開始地点」と「レイの方向ベクトル」、あと「三角ポリゴンの3つの頂点」<br />
を渡すとレイがポリゴンと交差しているかが判定できます。<br />
isDoubleSidedをtrueにすると裏向きのポリゴンも交差判定するようになります。<br />
交差しない場合はnullが返ってきて、交差する場合は<br />
交差点(position)と視点から交差点までの距離(distance)を含んだObjectが返ります。<br />
もっと処理を軽くする方法がありそうだけど、ひとまずこれで。<br /><br />あとはメッシュモデル内にある全三角ポリゴンと視線とを交差判定していけばおしまいなんですが・・・<br />
三角ポリゴン(Triangle3Dクラス)の各頂点がモデルの基点から見た相対的なローカル座標なので、<br />
モデルが回転していたりPapervision3Dとは座標系の違うcolladaファイルを使ってたりすると<br />正確な頂点座標でチェックできません（ここでしばらくつまづいてました）<br /><br />Papervision3Dで頂点のローカル座標をワールド座標に変換する方法ですが、<br /><br />
<ul><li>頂点ローカル座標にそのモデルの回転･移動･スケールを適用すればワールド座標になる</li><li>
モデルの最終的な回転･移動･スケールはDisplayObject3D.world（Matrix3Dクラス）で調べられる</li><li>Matrix3D.multiplyVector(Matrix3D, Number3D);でNumber3Dに変形後の座標が適用される</li></ul>
という事らしいので、<br />
<b>Matrix3D.multiplyVector(DisplayObject3D.world, 頂点座標);<br />
</b>でワールド座標に変換できる事がわかりました。<br />ちなみにMatrix3Dクラスというのは変換行列を扱うクラスで、<br />オブジェクトの移動・回転・スケールがまとまったものらしいです。<br /><br /><em>(追記)<br />DisplayObject3D.worldはシーンをレンダリングするタイミングでしか値が更新されない気がします。<br />レンダリング以外にworld値を更新するメソッドか何かがあればいいんだけど今のところみつからず･･･<br />どうしても常に回転しているオブジェクトのworld値をレンダリング直前に調べたいって場合は<br /><a href="http://www.morocoshi.net/blog/2009/09/displayobject3dtransform-1.html">こっちのエントリー</a>のコードで無理矢理調べる事もできます。</em><br /><br />
あとはワールド座標に変換した三角ポリゴンの3つの頂点で交差判定をしていきます。<br />
<pre class="brush: as3;">import org.papervision3d.core.geom.renderables.Triangle3D;
import org.papervision3d.core.geom.TriangleMesh3D;
import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.core.math.Number3D;
/**
 * 視線とメッシュの交差判定をする
 * @param	pos	レイ放射地点
 * @param	vec	レイの方向
 * @param	mesh	メッシュオブジェクト
 * @param	isDoubleSided	裏向きのポリゴンも交差判定する
 * @return
 */
public function collideRayToMesh(pos:Number3D, vec:Number3D, mesh:TriangleMesh3D, isDoubleSided:Boolean = false):Array {
	var res:Array = new Array();
	for each(var face:Triangle3D in mesh.geometry.faces) {
		var ps:Array = new Array();
		for (var i:int = 0; i &lt; 3; i++) {
			var n:Number3D = face["v" + String(i)].toNumber3D();
			//ここでnをワールド座標に変換
			Matrix3D.multiplyVector(mesh.world, n);
			ps.push(n);
		}
		var hit:Object = collideRayToTriangle(pos, vec, ps[0], ps[1], ps[2], isDoubleSided);
		if (hit != null) {
			hit.triangle = face;
			res.push(hit);
		}
	}
	res.sortOn("distance", Array.NUMERIC);
	return res;
}
</pre>
最初にメッシュモデル内の全ての三角ポリゴンを調べて、<br />各ポリゴンの3つの頂点をワールド座標にしてます。<br />ワールド座標にした頂点を使って交差判定をして、交差していれば配列に追加。<br />最後に交差結果の配列を交差点までの距離でソートして、
交差点が近い順に並べ替えています。<br />戻り値は交差情報を含んだObjectの配列で、交差したポリゴンの数だけ配列に格納されてます。<br />実際の使い方は↓こんな感じ。<br />
<pre class="brush:as3;">//交差チェック(結果の配列が0なら交差なし)
var list:Array = collideRayToMesh(pos, vec, mesh, isDoubleSided);
//最初に交差した三角ポリゴン(Triangle3D)の参照
trace(list[0].triangle);
//最初の交差点までの距離(Number)
trace(list[0].distance);
//最初の交差点の座標(Number3D)
trace(list[0].position);
</pre>

できたー。できたけど、多分重いんだろうな。。<br />サンプルはポリゴン少ないから問題なさそうだけど。<br />
<a href="http://www.morocoshi.net/blog/material/swf/collidetest1.swf" onclick="javascript:openswf(this.href, 400, 400, 9); return false;" target="_blank" class="openswf">
<img alt="collidetest1.jpg" src="http://www.morocoshi.net/blog/material/img/collidetest1.jpg" class="mt-image-none" style="" width="200" height="200" />
</a>
<br /><br />これでキャラクターの位置から真下にレイを飛ばして地面の高さを調べたり、<br />キャラクターの位置からカメラに向かってレイを飛ばして<br />カメラがポリゴン内に埋まっていないかをチェックできるかな。<br />]]>
    </content>
</entry>

</feed>
