9 嵌套(以太阳系为例)

嵌套

嵌套就是指将一个对象嵌入另一个容器对象中,当我们移动容器对象的时候,嵌入的对象也跟着容器对象移动。确切的说,嵌套就是将对象打包在一起形成一个整体,通过控制容器对象来整体移动。

当使用PV3D实现太阳系运行效果时,嵌套能很好的解决他们之间旋转、旋转速度的问题。下面我们以Sun、Earth、Moon的运行讲解嵌套。

第一步,在场景中创建一个大小为60的Sun对象sun,它被加载进场景的(0,0,0)。

第二步,创建一个大小为20的Earth对象earth,很自然,我们也将它加载进场景,并设置位置为600。

(1)       使用rotationY(按照其父容器的Y旋转,即场景Y轴)让earth旋转。但是Earth并没有绕着场景原点旋转,而是像自转一样。

(2)       使用localRotationY(按照其自身Y轴旋转)让earth旋转。Earth也没有绕着场景原点旋转,而是自转(方向和rotationY相反)。

PV3D提供给我们的2种旋转都不能解决地球绕场景原点旋转。在这里需要注意的是:虽然rotation和localRotation旋转坐标系统不同,但是它们都是在其中点,依据坐标系统旋转的。因此我们只能看到earth绕自身旋转。

第三步,将earth加载进sun,而不是场景。此时sun和earth嵌套成一个整体,让容器对象sun进行rotation旋转,可以看到容器对象中的所有嵌入的对象都跟着旋转。下图虚线表示sun和earth嵌套成一个整体。


我们了解的太阳系是以太阳为参照的,因此太阳相对太阳系的其他行星是静止的。为了解决这个问题,可以使用容器类DisplayObject3D。

第四步,创建一个DisplayObject3D对象earthContainer,将其放入场景。然后将earth对象加载进earthContainer,并在刷屏方法中让earthContainer对象进行rotationY旋转。此时earthContainer和earth嵌套为一个整体,容器对象(earthContainer)旋转带动earth旋转,这样earth就能绕着场景原点旋转了。


现在要解决的是如何让月球绕地球旋转。在这里需要注意的是月球有2种运行:

Ø        一种是绕太阳(场景原点)旋转

Ø        一种是绕地球旋转

一种简单的解决方法是:将创建的Moon对象moon加载进earth中,并在刷屏方法中让earth自转(localRotation)。这样earth带动moon旋转,且earthContainer带动moon绕太阳旋转。


这种方法简单,但是月球绕地球旋转的速度和地球自转一样,因为月球的旋转是由地球自转带动的。为了跟好的模拟太阳系运行效果,我们可以设置一个DisplayObject3D容器在earth的中心,让容器带动moon的旋转。

第五步,创建一个容器moonContainer,并将其加载进earthContainer容器中(earthContainer绕场景原点旋转),设置moonContainer的位置和earth一样。此时将moon加载进moonContainer中。并在刷屏方法中设置moonContainer的旋转速度。

下面在FlashDevelop中运行的代码:

package  
{
	import flash.events.Event;
	import mx.core.BitmapAsset;
	import org.papervision3d.materials.BitmapMaterial;
	import org.papervision3d.materials.ColorMaterial;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Cylinder;
	import org.papervision3d.objects.primitives.Sphere;
	import org.papervision3d.view.BasicView;
	/**
	 * ...
	 * @author yl
	 */
	[SWF(width = "800", height = "600", backgroundColor = "0x000000")]
	public class SunSys extends BasicView
	{
		private var sun:Sphere;
		private var earth:Sphere;
		private var moon:Sphere;
		private var earthContain:DisplayObject3D;
		private var water:Sphere;
		private var waterContain:DisplayObject3D;
		private var moonContain:DisplayObject3D;
		
		[Embed(source = "../assets/earth.jpg")] private var Earth:Class;
		[Embed(source = "../assets/moon.jpg")] private var Moon:Class;
		[Embed(source = "../assets/sun.jpg")] private var Sun:Class;
		[Embed(source = "../assets/water.jpg")] private var Water:Class;
		
		public function SunSys() 
		{
			earthContain = new DisplayObject3D();
			waterContain = new DisplayObject3D();
			moonContain = new DisplayObject3D();
			
			scene.addChild(waterContain);
			scene.addChild(moonContain);
			scene.addChild(earthContain);
			
			var sunAsset:BitmapAsset = new Sun() as BitmapAsset;
			var sunMaterial:BitmapMaterial = new BitmapMaterial(sunAsset.bitmapData);
			sun = new Sphere(sunMaterial, 60, 20, 20);
			scene.addChild(sun);
			
			var waterAsset:BitmapAsset = new Water() as BitmapAsset;
			var waterMaterial:BitmapMaterial = new BitmapMaterial(waterAsset.bitmapData);
			water = new Sphere(waterMaterial, 15, 20, 20);
			water.x = 200;
			waterContain.addChild(water);
			
			var earthAsset:BitmapAsset = new Earth() as BitmapAsset;
			var earthMaterial:BitmapMaterial = new BitmapMaterial(earthAsset.bitmapData);
			earth = new Sphere(earthMaterial, 20, 20, 20);
			earth.x = 600;
			earthContain.addChild(earth);
			
			moonContain.position = earth.position;
			earthContain.addChild(moonContain);
			
			var moonAsset:BitmapAsset = new Moon() as BitmapAsset;
			var moonMaterial:BitmapMaterial = new BitmapMaterial(moonAsset.bitmapData);
			moon = new Sphere(moonMaterial, 10, 20, 20);
			moon.x = 100;
			moonContain.addChild(moon);
			
			camera.y = 1000;
			camera.z = -1000;
			
			startRendering();
		}
		
		override protected function onRenderTick(e:Event = null):void {
			super.onRenderTick();
			
			earthContain.rotationY++;
			earth.localRotationY += 30;
			
			moonContain.rotationY += 5;
			
			waterContain.rotationY += 3;
		}
		
	}

}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值