Plane3D DisplayObject3Dを分割する
- 2009 年 7月 14 日
久々にPaperVision3D。
KYUCON*BLOGさんのこのエントリーを見て、
http://www.kyucon.com/blog/archives/000442.html
オブジェクトを分割できることを知らなかった僕には眉唾ものでした。
分割自体は、KYUCON*BLOGさんのサンプルがとっても分りやすいです。
細かいところだけれど分割で使っている、Plane3Dってクラスが良くわからなかったので、これを調べた覚え書き。
Plane3Dのコンストラクタは、
Plane3D(normal:Number3D = null, ptOnPlane:Number3D = null) |
3Dまわりの演算良くわかっていない僕なので、理系な方には余裕な話なんだと思いますが、Number3Dはリファレンスでなんとなくわかるにしても、これで分割面をどう定義すればよいものか。Plane3Dについてググってみたけど、日本語の情報はなかなか見つからなくて、辿り着いたのがこちら。
http://pv3d.org/2008/11/27/plane3d-intersect-poin/
こちらによると、Plane3Dは無限の平面とあります。
で、normalに渡すNumber3Dを
Number3D( 0, 1, 0 )
とすればX軸線がZ軸方向に無限に伸びた平面となる。
Number3D( 1, 0, 0 )ならY軸線がZ軸方向に無限に伸びた平面、
Number3D( 0, 0, 1 )ならX軸線がY軸方向に無限に伸びた平面となる。
それではと、
Number3D( 1, 1, 0 )にすると、正面から見て斜め45度の直線がZ軸方向に無限に伸びた平面になった。ちなみに、ptOnPlaneは面を置く座標っぽい。
なるほど…。これで理屈はわかります。
あとは、使いたい平面をどう作るかって話なんだけれど、これはKYUCON*BLOGさんのサンプルで使われている、3つの頂点を渡してつくるsetThreePointsとかいろいろメソッドが用意されているので適時試すとして、今回はここまでで良しとしました。
Number3D作ってNumber3Dで平面を回転させてみたサンプル。
package index{ import flash.events.Event; import org.papervision3d.core.utils.MeshUtil; import org.papervision3d.core.math.Plane3D; import org.papervision3d.core.math.Number3D; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.lights.PointLight3D; import org.papervision3d.materials.utils.MaterialsList; import org.papervision3d.materials.shadematerials.FlatShadeMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Cube; import org.papervision3d.view.BasicView; public class Main extends BasicView{ public function Main(viewportWidth:Number=400, viewportHeight:Number=400, scaleToStage:Boolean=true, interactive:Boolean=true, cameraType:String="TARGET"){ super(viewportWidth, viewportHeight, scaleToStage, interactive, cameraType); this.world = new DisplayObject3D(); this.scene.addChild( this.world ); this.light = new PointLight3D(); this.light.y= -1000; this.light.z= -1000; this.cube = new Cube( new MaterialsList( { all:new FlatShadeMaterial( this.light, 0xffffff, 0x00ff00, 50 ) } ) ); this.cube.material.doubleSided = true; this.num = new Number3D( 0, 0, 1 ); this.addEventListener( Event.ENTER_FRAME, this.enterFrameHandler, false, 0, true ); this.startRendering(); } public var light:PointLight3D public var world:DisplayObject3D; public var cube:Cube; public var num:Number3D; public function enterFrameHandler(e:Event):void{ var x:Number = ( this.stage.mouseX - this.stage.stageWidth / 2 ) / ( this.stage.stageWidth / 2 ); var y:Number = ( this.stage.mouseY - this.stage.stageHeight/ 2 ) / ( this.stage.stageWidth / 2 ); this.world.rotationY = x * 180; this.world.rotationX = y * 360; var plane3d:Plane3D = new Plane3D( this.num, Number3D.ZERO ); var arr:Array = MeshUtil.cutTriangleMesh( this.cube, plane3d ); for each( var i:DisplayObject3D in this.world.children ){ this.world.removeChild( i ); } var obj:DisplayObject3D = arr[0]; this.world.addChild( obj ); this.num.rotateX( 1 ); } } } |