加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Flash 与分布学构想:球体曲面分布

发布时间:2020-12-15 06:51:35 所属栏目:百科 来源:网络整理
导读:??????????? 我们在制作3D的时候,你是否经常会看到一些图片围绕成一个球体点进行分布,这些分布的方式呈现为球体形状,在这里我将它称作球体曲面分布。这种分布的情况,是依赖一个很常用的球体模型来制作。它涉及到一些关于几何的知识点,只要我们掌握到这

??????????? 我们在制作3D的时候,你是否经常会看到一些图片围绕成一个球体点进行分布,这些分布的方式呈现为球体形状,在这里我将它称作球体曲面分布。这种分布的情况,是依赖一个很常用的球体模型来制作。它涉及到一些关于几何的知识点,只要我们掌握到这种公式就能够创造一种比较好的球体效果。

??????????? 关于球体的公式,我查询了一些资料,发现这个公式并不唯一的。

??????????? 例如:?球体上的一点坐标:M(x,y,z)这个点记录了球体上的一个坐标信息。

???????????????????????? ?x=r*sin(a)*cos(b)(a 为纬度,b为经度 r为球体半径)

????????????????????????? y=r*sin(a) sin(b)

????????????????????????? z=r*cos(a)

?

??????????? 同样可以转变另外一种情况,它的坐标式参数方程为??

???????????????????????? ??x=r*cos(a)*cos(b)(a 为纬度,b为经度 r为球体半径)

????????????????????????? y=r*cos(a) sin(b)

????????????????????????? z=r*sin(a)

关于这个公式推导也是比较容易的,这些可以查询高等数学的几何介绍。

??? 有了这个公式后,制作flash 球体效果就容易多了。我们可以借助这个球面的参数方程制作一种3D球效果。注意到一点,数学上的模型和flash 里面是坐标系是不一样的,因此在使用的时候需要注意。

??? flash 当中 x 和 y 和z? 跟这个模型的显示 不一样,在这里我们只需要简单处理,将数学上是y的数值对应为 flash 当中z数值,z 数值对应为flash 当中y数值即可。x不变。接下来就是代码时候。

?

??????

??

?

?

package 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.*;
	public class Main extends Sprite
	{
		private var container:DisplayContainer3D;
		private var radius:Number = 600;//半径
		private var n:int = 6;         //定义6个图片
		private var perPhi:Number = Math.PI / (n + 1);
		public function Main():void
		{
			init();
		}

		private function init():void
		{
			container=new DisplayContainer3D();
			addChild(container);
			container.filters=[new GlowFilter(0xffffff)];
			container.x = stage.stageWidth / 2;
			container.y = stage.stageHeight / 2;
			container.z = 1200;//注意 尝试设置这个Z值可以和半径产生一定关系
			creatImage();
			addEventListener(Event.ENTER_FRAME,onStartMotion);
		}

		private function onStartMotion(event:Event):void
		{
			container.rotationY +=  0.2;
			container.sortZ();
		}
		private function creatImage():void
		{
			for (var i:int=1; i<=n; i++)
			{
				var phi:Number = perPhi * i;
				for (var j:int=0; j<10; j++)
				{
					var theta:Number = j * Math.PI * 2 / 10;
                    
					//建立球体公式
					var px:Number = radius * Math.sin(phi) * Math.cos(theta);
					var py:Number = radius * Math.cos(phi);
					var pz:Number = radius * Math.sin(phi) * Math.sin(theta);

					var image:Image=new Image();
					image.x = px;
					image.y = py;
					image.z = pz;

					image.rotationX = phi * 180 / Math.PI - 90;
					image.rotationY =  -  theta * 180 / Math.PI - 270;
					container.addList(image);
				}
			}
		}

	}

}
import flash.display.Sprite;
import flash.filters.*;

class Image extends Sprite
{

	public function Image()
	{
		this.graphics.lineStyle(8,0xffffff);
		this.graphics.beginFill(0x000000);
		this.graphics.drawRect( -50,-60,100,120);
		this.graphics.endFill();
		this.filters=[new GlowFilter(0xffffff)];
	}
}// this.filters=[new ]


?

//3d 容器类,用于z轴处理深度排序

package 
{
	import flash.display.*;
	import flash.geom.*;

	public class DisplayContainer3D extends Sprite
	{
		private var list:Array = [];
		public function DisplayContainer3D()
		{

		}

		public function addList(obj:*):void
		{
			list.push(obj);
			addChild(obj);			
		}

		public function get Arraylist():Array
		{
			return list;
		}

		public function sortZ():void
		{

			list.sort(depthSort);

			for (var i:int=0; i<list.length; i++)
			{
				var myimage:* = list[i];
				this.setChildIndex(myimage,i);
			}
		}


		private function depthSort(objA:DisplayObject,objB:DisplayObject):int
		{
			var posA:Vector3D = objA.transform.matrix3D.position;
			posA = this.transform.matrix3D.deltaTransformVector(posA);

			var posB:Vector3D = objB.transform.matrix3D.position;
			posB = this.transform.matrix3D.deltaTransformVector(posB);
			return posB.z-posA.z;
		}
	}


}


全部难点在于控制图片的偏移x和y值位置,这个地方比较难懂的。除了这种制作,变化球体 并不是一种的,在参考一些资料,3D球体变化有很多种。手法表现不一样,日后会记录一下以作参考使用。

?最后,加载外部一些图片,结合这种分布来进行图片处理,贴上这个最后效果图。看起来也挺不错的。除了旋转这种效果之外,交互的动作还是有很多。如拖放一个球体3D旋转,这种玩法比较有意思,可是flash cs类库当中 并没有提供封装好的摄影机,因此对这种单靠递增rotationY来取得球体效果还是不是很理想的。

好吧,一个简单的效果,只要我们记住这个公式实现这种3D球 还是很容易,不过这种求取分布位置的算法并不唯一,而还有很多种,日后会记录在这里。方便后来者使用。我相信只要善用这些分布技术,做flash的效果还是很容易上手,而除了游戏之外,这种交互多媒体还是挺好玩的。

?

?

?加载图片。

package 
{
	import flash.display.Sprite;
	import flash.events.*;
	import flash.display.Loader;
	import flash.net.URLRequest;
	import flash.display.Bitmap;

	public class QueueLoader  extends EventDispatcher
	{
		private var loaderMap:Array = [];
		private var current:int=0;//当前数目
		private var _arrayList:Array=[];
		private var _loadinfo:String;//加载进度信息
		private var total:int;//总数
		
		public static  const LOAD_COMPLETE:String="load_complete";
		public static  const LOAD_PROGRESS:String="load_progress";
		
		public function QueueLoader()
		{
					
		}
		//添加图片 
		public function addImage(path:String):void
		{
			var loader:Loader=new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onComplete);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,onError);
			
			var data:Object = {loader:loader,path:path};
			loaderMap.push(data);
			total++;
		}
		
		public function start():void
		{
			next();
		}

		//下一张图片 
		private function next():void
		{
			if (loaderMap.length > 0)
			{
				var data:Object = loaderMap.shift();
				data["loader"].load(new URLRequest(data["path"]));
			}
		}

		private function onComplete(event:Event):void
		{
			event.currentTarget.removeEventListener(Event.COMPLETE,onComplete);
			event.currentTarget.removeEventListener(IOErrorEvent.IO_ERROR,onError);
			
			var bitmap:Bitmap = event.currentTarget.content as Bitmap;
			_arrayList.push(bitmap);
			current++;
			this.dispatchEvent(new Event(QueueLoader.LOAD_PROGRESS));
			if(current==total)
			{
				this.dispatchEvent(new Event(QueueLoader.LOAD_COMPLETE));
			}
			next();
		}
        
		public function get arrayList():Array
		{
			return _arrayList;
		}
	
	    public function get loadingInfo():String
		{
			return current+"/"+total;
		}
	
		private function onError(event:IOErrorEvent):void
		{
			trace("错误了");
		}
	}
}

?

其中的图片,需要自己进行设置
loadingTxt 是在文档里面创建一个文本,用于图片显示图片加载进度。

定义 6x10的图片(可以看作二维数组。)

?

package 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.*;
	import flash.display.Bitmap;

	public class Main extends Sprite
	{
		private var container:DisplayContainer3D;
		private var radius:Number = 600;//半径
		private var n:int = 6;         //定义6个图片
		private var perPhi:Number = Math.PI / (n + 1);
		private var loader:QueueLoader=new QueueLoader();
		public function Main():void
		{
			init();
		}

		private function init():void
		{			
			for(var i:int=0;i<60;i++)
			{
				loader.addImage("images/"+(i+1)+".jpg");
			}
			
			loader.addEventListener(QueueLoader.LOAD_COMPLETE,onLoadComplete);
			loader.addEventListener(QueueLoader.LOAD_PROGRESS,onLoadProgress);
			loader.start();
			
			container=new DisplayContainer3D();
			addChild(container);
			container.x = stage.stageWidth / 2;
			container.y = stage.stageHeight / 2;
			container.z = 1200;//注意 尝试设置这个Z值可以和半径产生一定关系
			
			addEventListener(Event.ENTER_FRAME,onStartMotion);
		}

        private function onLoadComplete(event:Event):void
		{	
		    loader.removeEventListener(QueueLoader.LOAD_COMPLETE,onLoadComplete);
			loader.removeEventListener(QueueLoader.LOAD_PROGRESS,onLoadProgress);
			creatImage(loader.arrayList);
			removeChild(loadingTxt);
			loadingTxt=null;
		}
        
		private function onLoadProgress(event:Event):void
		{
			loadingTxt.text=loader.loadingInfo;
		}		
		
		private function onStartMotion(event:Event):void
		{
			container.rotationY +=  0.2;
			container.sortZ();
		}
		private function creatImage(array:Array):void
		{
			var k:int=0;
			for (var i:int=1; i<=n; i++)
			{
				var phi:Number = perPhi * i;
				for (var j:int=0; j<10; j++)
				{
					var theta:Number = j * Math.PI * 2 / 10;
                    
					//建立球体公式
					var px:Number = radius * Math.sin(phi) * Math.cos(theta);
					var py:Number = radius * Math.cos(phi);
					var pz:Number = radius * Math.sin(phi) * Math.sin(theta);

					var image:PhotoCantainer=new PhotoCantainer(array[k]);
					image.x = px;
					image.y = py;
					image.z = pz;

					image.rotationX = phi * 180 / Math.PI - 90;
					image.rotationY =  -  theta * 180 / Math.PI - 270;
					container.addList(image);
					k++;
				}
			}
		}
	}
}
import flash.display.Sprite;  
import flash.display.Bitmap;  
import flash.filters.DropShadowFilter;  
  
//图片容器   
internal class PhotoCantainer extends Sprite  
{  
  
    public function PhotoCantainer(bitmap:Bitmap)  
    {  
        addChild(bitmap);  
        bitmap.x =  -  bitmap.width / 2;  
        bitmap.y =  -  bitmap.height / 2;  
        drawBase(bitmap.width,bitmap.height);  
    }  
       
    //绘制白色底   
    private function drawBase(w:Number,h:Number):void  
    {  
        this.graphics.beginFill(0xffffff);  
        this.graphics.drawRect(-w/2-5,-h/2-5,w+10,h+10);  
        this.graphics.endFill();  
        this.filters = [new DropShadowFilter(3,45,0.5)];  
    }  
  
  
}  

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读