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

[3D]GeodesicSphere for Papervision3D

Papervison3d GeodesicSphere 테스트 
* 
* http://blog.jidolstar.com/643
* 
* @author Yongho, Ji
* @see texture http://visibleearth.nasa.gov/
/**
 * Copyright jidolstar ( http://wonderfl.net/user/jidolstar )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wX0O
 */

/**
 * Papervison3d GeodesicSphere 테스트 
 * 
 * http://blog.jidolstar.com/643
 * 
 * @author Yongho, Ji
 * @see texture http://visibleearth.nasa.gov/
 */ 
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=800, height=800, backgroundColor="#000000")]
	public class test_pv3d extends Sprite {
		private var _view:SphereView;
		private var _radius:Number=300;
		private var _fractures:Number=5;
		private var _showFrame:Boolean=true;

		public function test_pv3d() {
			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(stage.stageWidth, stage.stageHeight, _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=30;
			fractureSlider.labelPrecision=0;
			fractureSlider.value=_fractures;
			updateCount();
		}
	}
}

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

import flash.utils.*;

import org.papervision3d.Papervision3D;
import org.papervision3d.core.geom.TriangleMesh3D;
import org.papervision3d.core.geom.renderables.Triangle3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.core.math.NumberUV;
import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.view.BasicView;

/**
 * Sphere를 보여주는 화면 
 */ 
class SphereView extends BasicView {
	//[Embed(source="../assets/earthmap1k.jpg")]
	//private var SKY:Class;	

	private var _sphere:GeodesicSphere;
	private var _frameSphere:GeodesicSphere;
	private var _material:MaterialObject3D;
	private var _vx:Number=0;
	private var _vy:Number=0;

	public function SphereView($viewportWidth:Number, $viewportHeight:Number, $radius:Number, $fractures:Number, $viewframe:Boolean, $texture:BitmapData) {
		super($viewportWidth, $viewportHeight);
		_material=new BitmapMaterial($texture) as MaterialObject3D;
		_material.smooth=true;
		_material.doubleSided=false;
		createSphere($radius, $fractures, $viewframe);
		startRendering();
	}

	public function createSphere($radius:Number, $fractures:Number, $showFrame:Boolean):void {
		if (_sphere)
			scene.removeChild(_sphere);
		if (_frameSphere)
			scene.removeChild(_frameSphere);
		_sphere=new GeodesicSphere(_material, $radius, $fractures);
		scene.addChild(_sphere);
		if ($showFrame) {
			_frameSphere=new GeodesicSphere(new WireframeMaterial(0xffffff, 0.2, 1), $radius + 1, $fractures);
			scene.addChild(_frameSphere);
		}
	}

	override 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;
		var rotX:Matrix3D=Matrix3D.rotationX(_vx * Math.PI / 180);
		var rotY:Matrix3D=Matrix3D.rotationY(_vy * Math.PI / 180);
		var rotResult:Matrix3D=Matrix3D.multiply(rotX, rotY);
		_sphere.transform=Matrix3D.multiply(rotResult, tempMatrix);
		if (_frameSphere) {
			_frameSphere.transform=_sphere.transform;
		}
		super.onRenderTick($event);
	}

	public function getVertexCount():int {
		return _sphere.geometry.vertices.length;
	}
}

/**
 * GeodesicSphere 
 */ 
class GeodesicSphere extends TriangleMesh3D {
	static public var DEFAULT_RADIUS:Number=100;
	static public var DEFAULT_SCALE:Number=1;
	static public var MIN_FRACTURES:Number=0;

	public function GeodesicSphere($material:MaterialObject3D, $radius:Number=100, $fractures:int=8) {
		super($material, [], [], null);
		$fractures=Math.max(MIN_FRACTURES, $fractures);
		if ($radius == 0)
			$radius=DEFAULT_RADIUS;
		buildSphere($radius, $fractures);
	}

	private function buildSphere($radius:Number, $fractures:Number):void {
		var vertices:Array=geometry.vertices;
		var faces:Array=geometry.faces;
		var uvtData:Array=[];

		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 : 
		vertices.push(new Vertex3D(0, 0, -$radius));
		uvtData.push(new NumberUV(0, 0));
		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;
				vertices.push(new Vertex3D(x, y, z));
				uvtData.push(new NumberUV(u, v));
			}
		}

		//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;
				vertices.push(new Vertex3D(x, y, z));
				uvtData.push(new NumberUV(u, v));
			}
		}
		vertices.push(new Vertex3D(0, 0, $radius));
		uvtData.push(new NumberUV(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;
					}
					faces.push(new Triangle3D(this, [vertices[pt0], vertices[pt2], vertices[pt1]], material, [uvtData[pt0], uvtData[pt2], uvtData[pt1]]));
				}
			}
			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;
					}
					faces.push(new Triangle3D(this, [vertices[pt0], vertices[pt2], vertices[pt1]], material, [uvtData[pt0], uvtData[pt2], uvtData[pt1]]));
				}
			}
		}

		this.geometry.ready=true;

		if (Papervision3D.useRIGHTHANDED)
			this.geometry.flipFaces();
	}
}