In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

(Away3dlite) 지오데식 Sphere

Away3d Lite GeodesicSphere Test
*
* 
* texture http://visibleearth.nasa.gov/
*
* @author Yongho, Ji
* @see http://blog.jidolstar.com/589
* @see http://blog.jidolstar.com/643
Get Adobe Flash player
by jidolstar 09 Apr 2010
/**
 * Copyright jidolstar ( http://wonderfl.net/user/jidolstar )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/dnOL
 */

/**
 * Away3d Lite GeodesicSphere Test
 *
 * 
 * texture http://visibleearth.nasa.gov/
 *
 * @author Yongho, Ji
 * @see http://blog.jidolstar.com/589
 * @see http://blog.jidolstar.com/643
 */
package {
	import com.bit101.components.*;
	
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.text.*;
	import flash.ui.*;
	
	import net.hires.debug.Stats;
	
	[SWF(width=450, height=450, backgroundColor="#000000")]
	public class away3dlite_geodesic_sphere extends Sprite {
		private var _view:SphereView;
		private var _radius:Number=100;
		private var _fractures:Number=5;
		private var _showFrame:Boolean=true;
		
		public function away3dlite_geodesic_sphere() {
			super();
			stage.align=StageAlign.TOP_LEFT;
			stage.scaleMode=StageScaleMode.NO_SCALE;
			stage.frameRate=60;
			createSphereView();
			stage.addChild(new Stats());
		}
		
		private function createSphereView():void {
			var loader:Loader=new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void {
				var texture:BitmapData=Bitmap(loader.contentLoaderInfo.content).bitmapData;
				_view=new SphereView(_radius, _fractures, _showFrame, texture);
				stage.addChild(_view);
				createSphereViewController();
			});
			loader.load(new URLRequest("http://lab.alumican.net/wonderfl/fp10sphere/texture.png"), new LoaderContext(true));
		}
		
		private function createSphereViewController():void {
			var vertexCountLabel:Label=new Label(stage, 100, 86, "");
			var surfaceCountLabel:Label=new Label(stage, 180, 86, "");
			function updateCount():void {
				vertexCountLabel.text="vertex : " + String(_view.getVertexCount());
			}
			new Label(stage, 100, 10, "SHAPE");
			var fractureSlider:HUISlider=new HUISlider(stage, 100, 26, "fractures", function(e:Event):void {
				var fracture:Number=Math.round(e.target.value);
				if (fracture == _fractures)
					return;
				_fractures=fracture;
				_view.createSphere(_radius, _fractures, _showFrame);
				updateCount();
			});
			var radiusSlider:HUISlider=new HUISlider(stage, 100, 46, "Radius", function(e:Event):void {
				var radius:Number=Math.round(e.target.value);
				if (radius == _radius)
					return;
				_radius=radius;
				_view.createSphere(_radius, _fractures, _showFrame);
				updateCount();
			});
			var viewFrameCheckBox:CheckBox=new CheckBox(stage, 100, 66, "Show Wire Frame", function(e:Event):void {
				_showFrame=viewFrameCheckBox.selected;
				_view.createSphere(_radius, _fractures, _showFrame);
			});
			viewFrameCheckBox.selected=_showFrame;
			radiusSlider.minimum=10;
			radiusSlider.maximum=800;
			radiusSlider.labelPrecision=0;
			radiusSlider.value=_radius;
			fractureSlider.minimum=0;
			fractureSlider.maximum=10;
			fractureSlider.labelPrecision=0;
			fractureSlider.value=_fractures;
			updateCount();
		}
	}
}

import away3dlite.arcane;
import away3dlite.cameras.*;
import away3dlite.containers.*;
import away3dlite.containers.*;
import away3dlite.core.base.*;
import away3dlite.materials.*;
import away3dlite.primitives.*;

import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.net.URLRequest;
import flash.utils.*;

use namespace arcane;

/**
 * Sphere를 보여주는 화면
 */
class SphereView extends Sprite {
	//[Embed(source="../assets/earthmap1k.jpg")]
	//private var SKY:Class;	
	private var scene:Scene3D;
	private var camera:Camera3D
	private var view:View3D;
	private var _sphere:GeodesicSphere;
	private var _frameSphere:GeodesicSphere;
	private var _material:BitmapMaterial;
	private var _vx:Number=0;
	private var _vy:Number=0;
	private var rotX:Matrix3D=new Matrix3D();
	private var rotY:Matrix3D=new Matrix3D();
	private var rot:Matrix3D=new Matrix3D();
	
	public function SphereView($radius:Number, $fractures:Number, $viewframe:Boolean, $texture:BitmapData) {
		_material=new BitmapMaterial($texture);
		_material.smooth=true;
		scene=new Scene3D();
		camera=new Camera3D(1,1000);
		view=new View3D(scene, camera);
		addChild(view);
		createSphere($radius, $fractures, $viewframe);
		addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
	}
	
	private function onAddedToStage(event:Event):void {
		addEventListener(Event.ENTER_FRAME, onRenderTick);
		removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		addEventListener(Event.REMOVED_FROM_STAGE, onRemovedToStage);
		view.x=stage.stageWidth / 2;
		view.y=stage.stageHeight / 2;
	}
	
	private function onRemovedToStage($event:Event):void {
		addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedToStage);
		removeEventListener(Event.ENTER_FRAME, onRenderTick);
	}
	
	public function createSphere($radius:Number, $fractures:Number, $showFrame:Boolean):void {
		if (_sphere) {
			scene.removeChild(_sphere);
			_sphere = null;
		}
		if (_frameSphere) {
			scene.removeChild(_frameSphere);
			_frameSphere = null;
		}
		_sphere=new GeodesicSphere(_material, $radius, $fractures);
		scene.addChild(_sphere);
		
		if ($showFrame) {
			_frameSphere=new GeodesicSphere(new WireframeMaterial(0xffffff, 0.2), $radius + 1, $fractures);
			scene.addChild(_frameSphere);
		}
	}
	
	protected function onRenderTick($event:Event=null):void {
		_vx+=((mouseY / stage.stageHeight - 0.5) * 5 - _vx) * 0.3;
		_vy+=(-(mouseX / stage.stageWidth - 0.5) * 5 - _vy) * 0.3;
		//http://blog.federicocalvo.com/2009/03/papervision-3d-sphere-globla-axis.html
		var tempMatrix:Matrix3D=_sphere.transform.matrix3D;
		rotX.identity();
		rotX.appendRotation(_vx, Vector3D.X_AXIS);
		rotY.identity();
		rotY.appendRotation(_vy, Vector3D.Y_AXIS);
		rot.identity();
		rot.append(rotX);
		rot.append(rotY);
		tempMatrix.append(rot);
		_sphere.transform.matrix3D=tempMatrix.clone();
		if (_frameSphere) {
			_frameSphere.transform.matrix3D=tempMatrix.clone();
		}
		view.render();
	}
	
	public function getVertexCount():int {
		if (!_sphere)
			return 0;
		return _sphere.vertices.length;
	}
}

/**
 * Creates a 3d Geodesc sphere primitive.
 */
class GeodesicSphere extends AbstractPrimitive {
	private var _radius:Number;
	private var _fractures:Number;
	private var _yUp:Boolean=true;
	
	/**
	 * @inheritDoc
	 */
	protected override function buildPrimitive():void {
		super.buildPrimitive();
		
		var D2R:Number=Math.PI / 180; //Degree->Radian
		var R2D:Number=180 / Math.PI; //Radian->Degree
		var TPI:Number=Math.PI * 2;
		var PI:Number=Math.PI;
		var HPI:Number=Math.PI / 2;
		var hnLat:int=fractures + 1; //위도 방향 쪼갠수/2
		var nLat:int=2 * hnLat; //위도 방향 쪼갠수 
		var nLon:int; //위도에 대한 경도 방향 쪼갠수 
		var lon:Number; //경도 (단위:라디안)
		var lat:Number; //위도(단위:라디안)
		var dLat:Number=180 / nLat * D2R; //위도 간격(단위:라디안) 
		var dLon:Number; //경도  간격(단위:라디안)
		var i:int;
		var j:int;
		var x:Number;
		var y:Number;
		var z:Number;
		var sinLat:Number;
		var cosLat:Number;
		var sinLon:Number;
		var cosLon:Number;
		var u:Number;
		var v:Number;
		
		////////////////////////////////
		// Vertex, UVT 데이타 만들기
		////////////////////////////////	
		
		// latitude -90->0 : 
		x=0;
		y=0;
		z=-_radius;
		_yUp ? _vertices.push(x, -z, y) : _vertices.push(x, y, z);
		_uvtData.push(0, 0, 1);
		for (i=0; i < hnLat; i++) {
			nLon=4 * (i + 1); //경도방향 꼭지점수 4, 8, 12, 16, 20...
			dLon=360 / nLon * D2R;
			lat=-HPI + (i + 1) * dLat;
			v=(HPI + lat) / PI;
			sinLat=Math.sin(lat);
			cosLat=Math.cos(lat);
			z=radius * sinLat;
			for (j=0; j <= nLon; j++) {
				lon=j * dLon;
				sinLon=Math.sin(lon);
				cosLon=Math.cos(lon);
				x=radius * cosLat * cosLon;
				y=radius * cosLat * sinLon;
				u=lon / TPI;
				_yUp ? _vertices.push(x, -z, y) : _vertices.push(x, y, z);
				_uvtData.push(u, v, 1);
			}
		}
		
		//latitude 0 -> 90
		for (i=1; i < hnLat; i++) {
			nLon=4 * (hnLat - i);
			dLon=360 / nLon * D2R;
			lat=dLat * i;
			v=(HPI + lat) / PI;
			sinLat=Math.sin(lat);
			cosLat=Math.cos(lat);
			z=radius * sinLat;
			for (j=0; j <= nLon; j++) {
				lon=j * dLon;
				sinLon=Math.sin(lon);
				cosLon=Math.cos(lon);
				x=radius * cosLat * cosLon;
				y=radius * cosLat * sinLon;
				u=lon / TPI;
				_yUp ? _vertices.push(x, -z, y) : _vertices.push(x, y, z);
				_uvtData.push(u, v, 1);
			}
		}
		x=0;
		y=0;
		z=_radius;
		_yUp ? _vertices.push(x, -z, y) : _vertices.push(x, y, z);
		_uvtData.push(0, 1, 1);
		
		
		////////////////////////////////
		// Face 만들기 
		////////////////////////////////		
		var k:int;
		var pt0:int, pt1:int, pt2:int; //하나의 폴리곤을 생성하는 Vertex의 index값 
		var u_idx_start:int, u_idx_end:int, u_idx:int; //상단 index 
		var l_idx_start:int, l_idx_end:int, l_idx:int; //하단 index
		var isUp:int; //지그재그로 컬링 폴리곤을 생성하기 위해 
		var tris:int; //한개 분면에서 해당 적위에 대한 면의 수 
		var triIdx:int; //한개 분면에서 해당 적위에 대한 면의 수만큼 index를 증가하기 위해 사용 
		
		//Latitude -90->0    	
		tris=1;
		u_idx_start=0;
		u_idx_end=0;
		for (i=0; i < hnLat; ++i) {
			//위도 간격으로 상하  시작index와 끝 index를 지정 
			l_idx_start=u_idx_start;
			l_idx_end=u_idx_end;
			u_idx_start+=4 * i + 1;
			u_idx_end+=4 * (i + 1) + 1;
			l_idx=l_idx_start;
			u_idx=u_idx_start;
			
			//4분면을 따라 Face를 만들도록 한다. 
			for (k=0; k < 4; ++k) {
				isUp=1;
				//한개 분면에 대한 Face의 index를 만들어준다. 
				for (triIdx=0; triIdx < tris; ++triIdx) {
					if (isUp === 1) {
						pt0=l_idx;
						pt2=u_idx;
						u_idx++;
						pt1=u_idx;
						isUp=0;
					} else {
						pt0=u_idx;
						pt1=l_idx;
						l_idx++;
						pt2=l_idx;
						isUp=1;
					}
					_indices.push(pt0, pt1, pt2);
					//_faceLengths.push(3);
				}
			}
			tris+=2; //한개의 분면에서 해당 적위에 대한 면의 수는 2씩 증가한다. 
		}
		
		//Latitude 0 -> 90     	
		for (i=hnLat - 1; i >= 0; i--) {
			l_idx_start=u_idx_start;
			l_idx_end=u_idx_end;
			u_idx_start=u_idx_start + 4 * (i + 1) + 1;
			u_idx_end=u_idx_end + 4 * i + 1;
			tris-=2;
			u_idx=u_idx_start;
			l_idx=l_idx_start;
			for (k=0; k < 4; ++k) {
				isUp=0;
				for (triIdx=0; triIdx < tris; triIdx++) {
					if (isUp === 1) {
						pt0=l_idx;
						pt2=u_idx;
						u_idx++;
						pt1=u_idx;
						isUp=0;
					} else {
						pt0=u_idx;
						pt1=l_idx;
						l_idx++;
						pt2=l_idx;
						isUp=1;
					}
					_indices.push(pt0, pt1, pt2);
					//_faceLengths.push(3);
				}
			}
		}
	}
	
	/**
	 * Defines the radius of the sphere. Defaults to 100.
	 */
	public function get radius():Number {
		return _radius;
	}
	
	public function set radius(val:Number):void {
		if (_radius == val)
			return;
		
		_radius=val;
		_primitiveDirty=true;
	}
	
	/**
	 * Defines the fractures of the sphere. Defaults to 2.
	 */
	public function get fractures():Number {
		return _fractures;
	}
	
	public function set fractures(val:Number):void {
		if (_fractures == val)
			return;
		
		_fractures=val;
		_primitiveDirty=true;
	}
	
	/**
	 * Defines whether the coordinates of the plane points use a yUp orientation (true) or a zUp orientation (false). Defaults to true.
	 */
	public function get yUp():Boolean {
		return _yUp;
	}
	
	public function set yUp(val:Boolean):void {
		if (_yUp == val)
			return;
		
		_yUp=val;
		_primitiveDirty=true;
	}
	
	/**
	 * Creates a new <code>GeodesicSphere</code> object.
	 */
	public function GeodesicSphere(material:Material=null, radius:Number=100, fractures:int=2, yUp:Boolean=true) {
		super(material);
		
		_radius=radius;
		_fractures=fractures;
		_yUp=yUp;
		bothsides=false;
		
		type="GeodesicSphere";
		url="primitive";
	}
}