<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>整頓中（仮） &#187; papervison3D</title>
	<atom:link href="http://www.retropc.net/mm/archives/category/papervison3d/feed" rel="self" type="application/rss+xml" />
	<link>http://www.retropc.net/mm</link>
	<description>ずっと仮</description>
	<lastBuildDate>Wed, 08 Feb 2012 13:51:36 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Papervision3Dの描画順序</title>
		<link>http://www.retropc.net/mm/archives/154</link>
		<comments>http://www.retropc.net/mm/archives/154#comments</comments>
		<pubDate>Tue, 07 Apr 2009 07:51:03 +0000</pubDate>
		<dc:creator>moriyan</dc:creator>
				<category><![CDATA[papervison3D]]></category>

		<guid isPermaLink="false">http://www.retropc.net/mm/?p=154</guid>
		<description><![CDATA[papervison3Dを使って、単純なPlaneに接するようにCubeを描画した際に、Cubeの一部が欠けて表示されてしまいました。大きなプレーンがあって、その上に立方体が置いてあるようなイメージです。Cubeの欠け方を観察していると、Cubeの面を三角形に分割した形状で欠けが発生しています。 推測ですが、papervison3Dは描画にZソートを用いている事と、PlaneもCubeも三角形単位で描画している事が影響しているのだと思われます。大きなPlaneの三角形の重心の位置と小さなCubeの三角形の重心の位置の前後関係かなと。 なので、まず、単純なPlane同士の描画テストをしてみました。 [javascript toolbar="false"] package { import flash.display.MovieClip; import flash.events.Event; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.utils.Timer; import fl.controls.Slider; import fl.events.SliderEvent; import fl.controls.SliderDirection; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFieldType; import org.papervision3d.core.proto.CameraObject3D; import org.papervision3d.view.Viewport3D; import org.papervision3d.cameras.*; import org.papervision3d.scenes.Scene3D; import org.papervision3d.render.BasicRenderEngine; import org.papervision3d.objects.primitives.Plane; import org.papervision3d.materials.*; import org.papervision3d.materials.utils.*; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.core.proto.MaterialObject3D; import com.flashdynamix.utils.SWFProfiler; import caurina.transitions.*; public class [...]]]></description>
			<content:encoded><![CDATA[<p>papervison3Dを使って、単純なPlaneに接するようにCubeを描画した際に、Cubeの一部が欠けて表示されてしまいました。大きなプレーンがあって、その上に立方体が置いてあるようなイメージです。Cubeの欠け方を観察していると、Cubeの面を三角形に分割した形状で欠けが発生しています。<br />
推測ですが、papervison3Dは描画にZソートを用いている事と、PlaneもCubeも三角形単位で描画している事が影響しているのだと思われます。大きなPlaneの三角形の重心の位置と小さなCubeの三角形の重心の位置の前後関係かなと。</p>
<p>なので、まず、単純なPlane同士の描画テストをしてみました。</p>
<p><span id="more-154"></span></p>
<p style="text-align: center;"><a rel="shadowbox;width=640;height=360" href='/mm/wp/wp-content/uploads/2009/04/pv3layer01.swf'><img src="/mm/wp/wp-content/uploads/2009/04/pv3layer01.png" alt="pv3layer01" width="320" height="180" class="attachment wp-att-156 centered" /></a></p>
<p>[javascript toolbar="false"]<br />
package {<br />
	import flash.display.MovieClip;<br />
	import flash.events.Event;<br />
	import flash.events.MouseEvent;<br />
	import flash.events.TimerEvent;<br />
	import flash.utils.Timer;<br />
	import fl.controls.Slider;<br />
	import fl.events.SliderEvent;<br />
	import fl.controls.SliderDirection;<br />
	import flash.text.TextField;<br />
	import flash.text.TextFieldAutoSize;<br />
	import flash.text.TextFieldType;</p>
<p>	import org.papervision3d.core.proto.CameraObject3D;<br />
	import org.papervision3d.view.Viewport3D;<br />
	import org.papervision3d.cameras.*;<br />
	import org.papervision3d.scenes.Scene3D;<br />
	import org.papervision3d.render.BasicRenderEngine;<br />
	import org.papervision3d.objects.primitives.Plane;<br />
	import org.papervision3d.materials.*;<br />
	import org.papervision3d.materials.utils.*;<br />
	import org.papervision3d.objects.DisplayObject3D;<br />
	import org.papervision3d.core.proto.MaterialObject3D;</p>
<p>	import com.flashdynamix.utils.SWFProfiler;<br />
	import caurina.transitions.*;</p>
<p>	public class Main extends MovieClip {<br />
		public var scene:Scene3D;<br />
		public var renderer:BasicRenderEngine;<br />
		public var viewport:Viewport3D;<br />
		public var camera:Camera3D;</p>
<p>		private var txtFld:TextField;<br />
		private var nPlaneY:Number = 0;</p>
<p>		public function Main() {<br />
			SWFProfiler.init(stage, this);<br />
			init();<br />
		}</p>
<p>		public function init():void {<br />
			init3D();</p>
<p>			var aSlider:Slider = new Slider();<br />
			aSlider.direction = SliderDirection.VERTICAL;<br />
			aSlider.height = 360/2;<br />
			aSlider.x = 640-10;<br />
			aSlider.y = 360/4;<br />
			aSlider.tickInterval = 10;<br />
			aSlider.minimum = 0;<br />
			aSlider.maximum = 250;<br />
			aSlider.liveDragging = true;<br />
			aSlider.addEventListener(SliderEvent.CHANGE, aSliderChangeHandler);<br />
			addChild(aSlider);</p>
<p>			txtFld = new TextField();<br />
			txtFld.background = true;<br />
			txtFld.width = 30;<br />
			txtFld.height = 18;<br />
			txtFld.x = 640-30;<br />
			txtFld.y = 360-18;<br />
			txtFld.text = &#8220;0&#8243;;<br />
			addChild(txtFld);</p>
<p>			addEventListener(Event.ENTER_FRAME, loop);<br />
			var timer:Timer = new Timer(250);<br />
			timer.addEventListener(TimerEvent.TIMER, timerFunc);<br />
			timer.start();<br />
		}</p>
<p>		private function aSliderChangeHandler(evt:SliderEvent)<br />
		{<br />
			nPlaneY = evt.value;<br />
			txtFld.text = nPlaneY.toString();<br />
		}</p>
<p>		public function timerFunc(e:TimerEvent):void {<br />
			var material:ColorMaterial = new ColorMaterial(0xa0a0e0);<br />
			var myPlane:Plane = new Plane(material, 50, 50, 1, 1);<br />
			myPlane.x = Math.random()*400 &#8211; 200;<br />
			myPlane.y = nPlaneY;<br />
			myPlane.z = 1500;<br />
			myPlane.rotationX = 90;<br />
			scene.addChild(myPlane);<br />
			Tweener.addTween( myPlane, { z:-1500, time:25, onComplete:animEnd, onCompleteParams:[ myPlane ] } );<br />
		}</p>
<p>		public function animEnd(varPlane:Plane):void {<br />
			scene.removeChild(varPlane);<br />
			varPlane = null;<br />
		}</p>
<p>		public function init3D():void {<br />
			viewport = new Viewport3D(0, 0, true, true);<br />
			addChild(viewport);<br />
			renderer = new BasicRenderEngine();<br />
			scene = new Scene3D();</p>
<p>			var material:ColorMaterial = new ColorMaterial( 0x2080e0 );<br />
			material.oneSide = false;<br />
			var myPlane:Plane = new Plane(material, 500, 500, 1, 1);<br />
			myPlane.rotationX = 90;<br />
			scene.addChild(myPlane);</p>
<p>			camera = new Camera3D();<br />
			camera.zoom = 50;<br />
			camera.y = 200;<br />
			camera.orbit(20, -30, true, myPlane);<br />
		}</p>
<p>		public function loop(event:Event):void {<br />
			renderer.renderScene(scene, camera, viewport);<br />
		}<br />
	}<br />
}<br />
[/javascript]</p>
<p>大きな板の上を小さな板が通過しています。右側のライダーを動かすと、小さな板の高さ方向の位置が変化するのですが、100ぐらいまで移動させたところで欠けがなくなりますから、表示位置を調整する事で欠けを回避できます。<br />
ただし、板の位置が100だけ上に移動しているので、大きな板と小さな板の間には100の隙間があるということになります。なので、小さな板の見え方が変わりますし（カメラに寄るので大きくなっています）、カメラが固定なら問題ありませんが、カメラが正面にでも移動したら、隙間が見えてしまうのです。</p>
<p>papervison3Dの描画処理は、Zソートと三角形の描画です。カメラの位置よりも遠い（と判断された）三角形から順に画面に描かれます。つまり、手前の三角形を上に上描きすることで前後関係の描画をしているのです。なので、前後関係の判定結果が想定したものにならないと見た目が破綻します。</p>
<p>それならもういっそのこと、とにかく下にある板を先に描画して、その後に小さな板を描画してくれればいいいわけで、papervison3DのViewportLayerを使うと実現できるようです。</p>
<p><a rel="shadowbox;width=640;height=360" href='/mm/wp/wp-content/uploads/2009/04/pv3layer02.swf'>描画順位を指定したサンプルSWF</a></p>
<p>[javascript toolbar="false"]<br />
package {<br />
	import flash.display.MovieClip;<br />
	import flash.events.Event;<br />
	import flash.events.MouseEvent;<br />
	import flash.events.TimerEvent;<br />
	import flash.utils.Timer;</p>
<p>	import org.papervision3d.core.proto.CameraObject3D;<br />
	import org.papervision3d.view.Viewport3D;<br />
	import org.papervision3d.cameras.*;<br />
	import org.papervision3d.scenes.Scene3D;<br />
	import org.papervision3d.render.BasicRenderEngine;<br />
	import org.papervision3d.objects.primitives.Plane;<br />
	import org.papervision3d.materials.*;<br />
	import org.papervision3d.materials.utils.*;<br />
	import org.papervision3d.objects.DisplayObject3D;<br />
	import org.papervision3d.core.proto.MaterialObject3D;</p>
<p>	import org.papervision3d.view.layer.ViewportLayer;<br />
	import org.papervision3d.view.layer.util.ViewportLayerSortMode;</p>
<p>	import com.flashdynamix.utils.SWFProfiler;<br />
	import caurina.transitions.*;</p>
<p>	public class Main extends MovieClip {<br />
		public var scene:Scene3D;<br />
		public var renderer:BasicRenderEngine;<br />
		public var viewport:Viewport3D;<br />
		public var camera:Camera3D;</p>
<p>		public function Main() {<br />
			SWFProfiler.init(stage, this);<br />
			init();<br />
		}</p>
<p>		public function init():void {<br />
			init3D();<br />
			addEventListener(Event.ENTER_FRAME, loop);<br />
			var timer:Timer = new Timer(250);<br />
			timer.addEventListener(TimerEvent.TIMER, timerFunc);<br />
			timer.start();<br />
		}</p>
<p>		public function timerFunc(e:TimerEvent):void {<br />
			var material:ColorMaterial = new ColorMaterial(0xa0a0e0);<br />
			var myPlane:Plane = new Plane(material, 50, 50, 1, 1);<br />
			myPlane.x = Math.random()*400 &#8211; 200;<br />
			myPlane.y = 1;<br />
			myPlane.z = 1500;<br />
			myPlane.rotationX = 90;</p>
<p>			var viewportLayer:ViewportLayer = new ViewportLayer(viewport, myPlane);<br />
			viewportLayer.layerIndex = 1;<br />
			viewport.containerSprite.addLayer(viewportLayer);</p>
<p>			scene.addChild(myPlane);<br />
			Tweener.addTween( myPlane, { z:-1500, time:25, onComplete:animEnd, onCompleteParams:[ myPlane ] } );<br />
		}</p>
<p>		public function animEnd(varPlane:Plane):void {<br />
			scene.removeChild(varPlane);<br />
			varPlane = null;<br />
		}</p>
<p>		public function init3D():void {<br />
			viewport = new Viewport3D(0, 0, true, true);<br />
			addChild(viewport);<br />
			renderer = new BasicRenderEngine();<br />
			scene = new Scene3D();</p>
<p>			var material:ColorMaterial = new ColorMaterial( 0x2080e0 );<br />
			material.oneSide = false;<br />
			var myPlane:Plane = new Plane(material, 500, 500, 1, 1);<br />
			myPlane.rotationX = 90;<br />
			scene.addChild(myPlane);</p>
<p>			camera = new Camera3D();<br />
			camera.zoom = 50;<br />
			camera.y = 200;<br />
			camera.orbit(20, -30, true, myPlane);</p>
<p>			viewport.containerSprite.sortMode = ViewportLayerSortMode.INDEX_SORT;</p>
<p>			var viewportLayer:ViewportLayer = new ViewportLayer(viewport, myPlane);<br />
			viewportLayer.layerIndex = 0;<br />
			viewport.containerSprite.addLayer(viewportLayer);<br />
		}</p>
<p>		public function loop(event:Event):void {<br />
			renderer.renderScene(scene, camera, viewport);<br />
		}<br />
	}<br />
}<br />
[/javascript]</p>
<p>小さな板の高さ座標は1にしてあります。位置が0の大きな板よりも1だけ離れた位置です。大きな板と同じ位置の0でもいいのですが同じ座標だと埋まっている印象なので、ちょっとだけ上にある感じです。大きな板のlayerIndexは0、小さな板のlayerIndexは生成するたびに1に設定しています。このようにすると、どんな状態であっても、大きな板を描いてから小さな板を描くようです。</p>
<p>「どんな状態であっても」ということは、小さな板が大きな板の下にあるような状態であっても、小さな板が後に（手前に）描画されます。例えば、大きな板の下にカメラが移動して大きな板を見上げた場合でも、小さな板が後に描画されるので、前後関係がおかしくなります。こういう単純なサンプルの場合は、大きな板の位置が0で固定されているので、カメラの位置が0未満の場合は大きな板のlayerIndexを小さな板のlayerIndexよりも大きな値に設定すれば済みます。</p>
<p>これがViewportLayer本来の使い方なのかどうかはわかりません。<a href="http://d.hatena.ne.jp/mugaki/">ひだちのいろの日記</a>さんの<a href="http://d.hatena.ne.jp/mugaki/20081020/1224508846">3D オブジェクトの ViewportLayerにアクセスする</a>を読むとオブジェクト単位で何か処理を施す場合にViewportLayerを使うようですし、layerIndexが同じ3Dオブジェクトの描画順序はどうなるのか（Zソートされる？）というような別の疑問は残っています。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.retropc.net/mm/archives/154/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

