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

forked from: forked from: Checkmate Vol.6 Amatuer

/**
 * Copyright hacker__3lnbuxt ( http://wonderfl.net/user/hacker__3lnbuxt )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/dpfO
 */

// forked from sekiryou's forked from: Checkmate Vol.6 Amatuer
// forked from checkmate's Checkmate Vol.6 Amatuer
package {
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.text.*;
	
	[SWF(width = "465", height = "465", backgroundColor = "0x000000", frameRate = "30")]
	
	public class FeelTheWind extends Sprite {
        private const STAGE_WIDTH:uint = 465;
        private const STAGE_HEIGHT:uint = 465;
        private const STAGE_CENTER_X:Number = STAGE_WIDTH * 0.5;
        private const STAGE_CENTER_Y:Number = STAGE_HEIGHT * 0.5;
		private var canvas:BitmapData;
		private var screen:Sprite;
		private var mtx3D:Matrix3D = new Matrix3D();
		private var projection:PerspectiveProjection;
		private var projectionMatrix3D:Matrix3D;
		private var skirt:Skirt = new Skirt();
		
		public function FeelTheWind() {
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			addChild( new Bitmap( canvas = new BitmapData( STAGE_WIDTH, STAGE_HEIGHT, true, 0xFF000000 ) ) );
			addChild( screen = new Sprite() );
			screen.alpha = 0;
			screen.x = STAGE_CENTER_X;
			screen.y = STAGE_CENTER_Y;
			projection = new PerspectiveProjection();
			projection.fieldOfView = 30;
			projectionMatrix3D = projection.toMatrix3D();
			addEventListener( Event.ENTER_FRAME, onEnterFrameHandler );
			addEventListener( Event.ENTER_FRAME,
				function( eventObject:Event ):void {
					if ( screen.alpha < 1 ) {
						screen.alpha += 0.04;
					} else {
						removeEventListener( Event.ENTER_FRAME, arguments.callee );
						start();
					}
				}
			);
			
			tf = new TextFormat();
			tf.font = "Verdana";
			tf.size = 12;
			scoreBoardDesign();
			gaugeDesign();
		}
		private var tf:TextFormat;
		private var score1st:TextField;
		private var score2nd:TextField;
		private var score3rd:TextField;
		private var scoreTotal:TextField;
		private var retryButton:Sprite;
		private var cullingButton:Sprite;
		private var windDirection:Sprite;
		private var windDirectionGauge:Sprite;
		private var windForceGauge:Sprite;
		private var forceGauge:Sprite;
		private var clickDirection:Sprite;
		private var clickForce:Sprite;
		private var resultBoard:Sprite;
		private var resultScore:TextField;
		private var resultGrade:TextField;
		private function scoreBoardDesign():void {
			var captionScore:TextField = new TextField();
			captionScore.autoSize = TextFieldAutoSize.LEFT;
			captionScore.x = 10;
			captionScore.y = 10;
			captionScore.selectable = false;
			captionScore.textColor = 0xFFFFFF;
			captionScore.defaultTextFormat = tf;
			captionScore.text = "SCORE";
			addChild( captionScore );
			
			cullingButton = new Sprite();
			//cullingButton.graphics.lineStyle( 1, 0x999900 )
			cullingButton.graphics.beginFill( 0x000000, 0 );			
			cullingButton.graphics.drawRect( -32, -12, 64, 24 );
			cullingButton.graphics.endFill();
			cullingButton.x = 32;
			cullingButton.y = 18;
			addChild( cullingButton );
			cullingButton.buttonMode = true;
			cullingButton.mouseChildren = false;
			cullingButton.addEventListener( MouseEvent.MOUSE_DOWN,
				function( eventObject:MouseEvent ):void {
					cullingFlag = !cullingFlag
				}
			);
			
			var cap1st:TextField = new TextField();
			cap1st.autoSize = TextFieldAutoSize.LEFT;
			cap1st.x = 20;
			cap1st.y = 30;
			cap1st.selectable = false;
			cap1st.textColor = 0xFFFFFF;
			cap1st.defaultTextFormat = tf;
			cap1st.text = "1st";
			addChild( cap1st );
			
			var cap2nd:TextField = new TextField();
			cap2nd.autoSize = TextFieldAutoSize.LEFT;
			cap2nd.x = 20;
			cap2nd.y = 50;
			cap2nd.selectable = false;
			cap2nd.textColor = 0xFFFFFF;
			cap2nd.defaultTextFormat = tf;
			cap2nd.text = "2nd";
			addChild( cap2nd );
			
			var cap3rd:TextField = new TextField();
			cap3rd.autoSize = TextFieldAutoSize.LEFT;
			cap3rd.x = 20;
			cap3rd.y = 70;
			cap3rd.selectable = false;
			cap3rd.textColor = 0xFFFFFF;
			cap3rd.defaultTextFormat = tf;
			cap3rd.text = "3rd";
			addChild( cap3rd );
			
			var capTotal:TextField = new TextField();
			capTotal.autoSize = TextFieldAutoSize.LEFT;
			capTotal.x = 20;
			capTotal.y = 90;
			capTotal.selectable = false;
			capTotal.textColor = 0xFFFFFF;
			capTotal.defaultTextFormat = tf;
			capTotal.text = "TOTAL";
			addChild( capTotal );
			
			
			score1st = new TextField();
			score1st.autoSize = TextFieldAutoSize.RIGHT;
			score1st.x = 120;
			score1st.y = 30;
			score1st.selectable = false;
			score1st.textColor = 0xFFFFFF;
			score1st.defaultTextFormat = tf;
			score1st.text = "0";
			addChild( score1st );
			
			score2nd = new TextField();
			score2nd.autoSize = TextFieldAutoSize.RIGHT;
			score2nd.x = 120;
			score2nd.y = 50;
			score2nd.selectable = false;
			score2nd.textColor = 0xFFFFFF;
			score2nd.defaultTextFormat = tf;
			score2nd.text = "0";
			addChild( score2nd );
			
			score3rd = new TextField();
			score3rd.autoSize = TextFieldAutoSize.RIGHT;
			score3rd.x = 120;
			score3rd.y = 70;
			score3rd.selectable = false;
			score3rd.textColor = 0xFFFFFF;
			score3rd.defaultTextFormat = tf;
			score3rd.text = "0";
			addChild( score3rd );
			
			scoreTotal = new TextField();
			scoreTotal.autoSize = TextFieldAutoSize.RIGHT;
			scoreTotal.x = 120;
			scoreTotal.y = 90;
			scoreTotal.selectable = false;
			scoreTotal.textColor = 0xFFFFFF;
			scoreTotal.defaultTextFormat = tf;
			scoreTotal.text = "0";
			addChild( scoreTotal );
			
			var capResult:TextField = new TextField();
			capResult.autoSize = TextFieldAutoSize.CENTER;
			capResult.x = 0;
			capResult.y = -45;
			capResult.selectable = false;
			capResult.textColor = 0xFFFF00;
			capResult.defaultTextFormat = tf;
			capResult.text = "RESULT";
			
			resultScore = new TextField();
			resultScore.autoSize = TextFieldAutoSize.CENTER;
			resultScore.x = 0;
			resultScore.y = -15;
			resultScore.selectable = false;
			resultScore.textColor = 0xFFFFFF;
			resultScore.defaultTextFormat = tf;
			resultScore.text = "SCORE";
			
			resultGrade = new TextField();
			resultGrade.autoSize = TextFieldAutoSize.CENTER;
			resultGrade.x = 0;
			resultGrade.y = 15;
			resultGrade.selectable = false;
			resultGrade.textColor = 0xFFFFFF;
			resultGrade.defaultTextFormat = tf;
			resultGrade.text = "GRADE";
			
			resultBoard = new Sprite();
			resultBoard.graphics.lineStyle( 1, 0x999900 )
			resultBoard.graphics.beginFill( 0x000000, 0.5 );			
			resultBoard.graphics.drawRect( -80, -50, 160, 100 );
			resultBoard.graphics.endFill();
			resultBoard.x = STAGE_CENTER_X;
			resultBoard.y = STAGE_CENTER_Y;
			addChild( resultBoard );
			resultBoard.addChild( capResult );
			resultBoard.addChild( resultScore );
			resultBoard.addChild( resultGrade );
			resultBoard.visible = false;
			
			var retry:TextField = new TextField();
			retry.autoSize = TextFieldAutoSize.CENTER;
			retry.x = 0;
			retry.y = -9;
			retry.selectable = false;
			retry.textColor = 0xFFFFFF;
			retry.defaultTextFormat = tf;
			retry.text = "RETRY";
			
			retryButton = new Sprite();
			retryButton.graphics.lineStyle( 1, 0x999900 )
			retryButton.graphics.beginFill( 0x000000, 0 );			
			retryButton.graphics.drawRect( -32, -12, 64, 24 );
			retryButton.graphics.endFill();
			retryButton.x = 420;
			retryButton.y = 30;
			addChild( retryButton );
			retryButton.addChild( retry );
			retryButton.visible = false;
			retryButton.buttonMode = true;
			retryButton.mouseChildren = false;
			retryButton.addEventListener( MouseEvent.MOUSE_DOWN, start );
		}
		private function gaugeDesign():void {
			var north:TextField = new TextField();
			north.autoSize = TextFieldAutoSize.CENTER;
			north.x = 158;
			north.y = 320;
			north.selectable = false;
			north.textColor = 0xFFFFFF;
			north.defaultTextFormat = tf;
			north.text = "N";
			addChild( north );
			
			addChild( windDirection = new Sprite() );
			windDirection.graphics.beginGradientFill( GradientType.LINEAR, [0x0000FF, 0xFFFFFF], [1, 1], [0x00, 0xFF] );
			windDirection.graphics.lineStyle( 1.0, 0xFFFFFF );
			windDirection.graphics.moveTo( 0, 0 );
			windDirection.graphics.lineTo( 10, 35 );
			windDirection.graphics.lineTo( 0, 30 );
			windDirection.graphics.lineTo( -10, 35 );
			windDirection.graphics.lineTo( 0, 0 );
			windDirection.x = 160;
			windDirection.y = 380;
			
			addChild( windDirectionGauge = new Sprite() );
			windDirectionGauge.graphics.lineStyle( 1.0, 0xFFFFFF );
			windDirectionGauge.graphics.drawCircle( 0, 0, 10 );
			windDirectionGauge.graphics.drawCircle( 0, 0, 30 );
			windDirectionGauge.graphics.moveTo( -40, 0 );
			windDirectionGauge.graphics.lineTo( 40, 0 );
			windDirectionGauge.graphics.moveTo( 0, -40 );
			windDirectionGauge.graphics.lineTo( 0, 40 );
			windDirectionGauge.x = 160;
			windDirectionGauge.y = 380;
			
			var forceBaseGauge:Sprite = new Sprite();
			forceBaseGauge.graphics.lineStyle( 1.0, 0xFFFFFF );
			forceBaseGauge.graphics.beginFill( 0xFF0000 );
			forceBaseGauge.graphics.drawRect( 0, 0, 100, 5 );
			forceBaseGauge.graphics.endFill();			
			forceBaseGauge.x = 260;
			forceBaseGauge.y = 380;
			addChild( forceBaseGauge );
			
			addChild( forceGauge = new Sprite() );
			forceGauge.graphics.lineStyle( 1.0, 0xFFFFFF );
			forceGauge.graphics.beginFill( 0xFFFF00 );
			forceGauge.graphics.drawRect( 0, 0, 100, 5 );
			forceGauge.graphics.endFill();			
			forceGauge.x = 260;
			forceGauge.y = 380;
			
			var capDirection:TextField = new TextField();
			capDirection.autoSize = TextFieldAutoSize.CENTER;
			capDirection.x = 160;
			capDirection.y = 430;
			capDirection.selectable = false;
			capDirection.textColor = 0xFFFFFF;
			capDirection.defaultTextFormat = tf;
			capDirection.text = "Direction";
			addChild( capDirection );
			
			var capForce:TextField = new TextField();
			capForce.autoSize = TextFieldAutoSize.CENTER;
			capForce.x = 310;
			capForce.y = 430;
			capForce.selectable = false;
			capForce.textColor = 0xFFFFFF;
			capForce.defaultTextFormat = tf;
			capForce.text = "Force";
			addChild( capForce );
			
			var capDirectClick:TextField = new TextField();
			capDirectClick.autoSize = TextFieldAutoSize.CENTER;
			capDirectClick.x = 0;
			capDirectClick.y = -90;
			capDirectClick.selectable = false;
			capDirectClick.textColor = 0xFFFF00;
			capDirectClick.defaultTextFormat = tf;
			capDirectClick.text = "CLICK";
			
			clickDirection = new Sprite();
			clickDirection.graphics.lineStyle( 1, 0x999900 )
			clickDirection.graphics.beginFill( 0x000000, 0 );			
			clickDirection.graphics.drawRect( -65, -70, 130, 140 );
			clickDirection.graphics.endFill();
			clickDirection.x = 160;
			clickDirection.y = 385;
			addChild( clickDirection );
			clickDirection.addChild( capDirectClick );
			clickDirection.visible = false;
			clickDirection.buttonMode = true;
			clickDirection.mouseChildren = false;
			clickDirection.addEventListener( MouseEvent.MOUSE_DOWN,
				function( eventObject:MouseEvent ):void {
					decisionDirection = true;
				}
			);
			
			var capForceClick:TextField = new TextField();
			capForceClick.autoSize = TextFieldAutoSize.CENTER;
			capForceClick.x = 0;
			capForceClick.y = -90;
			capForceClick.selectable = false;
			capForceClick.textColor = 0xFFFF00;
			capForceClick.defaultTextFormat = tf;
			capForceClick.text = "CLICK";
			
			clickForce = new Sprite();
			clickForce.graphics.lineStyle( 1, 0x999900 );
			clickForce.graphics.beginFill( 0x000000, 0 );			
			clickForce.graphics.drawRect( -65, -70, 130, 140 );
			clickForce.graphics.endFill();
			clickForce.x = 310;
			clickForce.y = 385;
			addChild( clickForce );
			clickForce.addChild( capForceClick );
			clickForce.visible = false;
			clickForce.buttonMode = true;
			clickForce.mouseChildren = false;
			clickForce.addEventListener( MouseEvent.MOUSE_DOWN,
				function( eventObject:MouseEvent ):void {
					decisionForce = true;
				}
			);
		}
		private var trying:uint;
		private var score:Array;
		private var decisionForce:Boolean;
		private var decisionDirection:Boolean;
		private var windFlag:Boolean;
		private var windDuration:int;
		private var windPower:Number;
		private var windPowerX:Number;
		private var windPowerY:Number;
		private var windPowerZ:Number;
		private var windDecrease:Number;
		private const DEGREE_TO_RADIAN:Number = Math.PI / 180;
		private function gameControl( eventObject:Event ):void {
			var windTrans:Function = function():void {
				var tmpDirect:Number = ( windDirection.rotation + 90 ) * DEGREE_TO_RADIAN;
				windPowerX = Math.cos( tmpDirect ) * -windPower;
				windPowerY = -windPower;
				windPowerZ = Math.sin( tmpDirect ) * windPower;
			}
			if ( windFlag ) {
				if ( windDuration >= 0 ) {
					windDuration -= 1;
				} else {
					if ( windPower > 0 ) {
						windTrans();
						windPower -= windDecrease;
					} else {
						windFlag = false;
						windPowerX = 0;
						windPowerY = 0;
						windPowerZ = 0;
						if ( trying < 3 ) {
							clickDirection.visible = true;
							clickForce.visible = true;
						}
					}
				}
			} else {
				if ( trying > 2 ) {
					removeEventListener( Event.ENTER_FRAME, gameControl );
					result();
				} else {
					if ( !decisionDirection ) {
						windDirection.rotation += 20;
					} else {
						clickDirection.visible = false;
					}
					if ( !decisionForce ) {
						forceGauge.scaleX += 0.08;
						if ( forceGauge.scaleX > 1.0 ) {
							forceGauge.scaleX = 0.04;
						}
					} else {
						clickForce.visible = false;
					}
					if ( decisionDirection && decisionForce ) {
						windPower = forceGauge.scaleX * 1.6 * 0.3;
						windTrans();
						score[ trying ] = int( ( ( 200 - Math.abs( windDirection.rotation ) ) * 0.1 ) * ( forceGauge.scaleX * 10 ) );
						scoreUpdate();
						windDecrease = windPower / 75;
						windDuration = 50;
						windFlag = true;
						decisionDirection = false;
						decisionForce = false;
						trying += 1;
					}
				}
			}
		}
		private function start( eventObject:MouseEvent = null ):void {
			resultBoard.visible = false;
			retryButton.visible = false;
			trying = 0;
			score = [ 0, 0, 0 ];
			scoreUpdate();
			decisionForce = false;
			decisionDirection = false;
			windFlag = false;
			windPowerX = 0;
			windPowerY = 0;
			windPowerZ = 0;
			clickDirection.visible = true;
			clickForce.visible = true;
			addEventListener( Event.ENTER_FRAME, gameControl );
		}
		private function scoreUpdate():void {
			score1st.text = score[ 0 ];
			score2nd.text = score[ 1 ];
			score3rd.text = score[ 2 ];
			scoreTotal.text = score[ 0 ] + score[ 1 ] + score[ 2 ];
		}
		private function result():void {
			var tmpScore:Number = score[ 0 ] + score[ 1 ] + score[ 2 ];
			resultScore.text = "SCORE : " + tmpScore;
			if ( tmpScore > 520 ) {
				resultGrade.text = "GRADE : EXCELLENT";
			} else if ( tmpScore > 420 ) {
				resultGrade.text = "GRADE : GREAT";
			} else if ( tmpScore > 300 ) {
				resultGrade.text = "GRADE : GOOD";
			} else if ( tmpScore > 150 ) {
				resultGrade.text = "GRADE : BAD";
			} else {
				resultGrade.text = "GRADE : POOR";
			}
			resultBoard.visible = true;
			retryButton.visible = true;
		}
		private var viewMoveX:Number = 0;
		private var viewMoveY:Number = 0;
		private var cullingFlag:Boolean = true;
		private function onEnterFrameHandler( eventObject:Event ):void {
			var projectedVerts:Vector.<Number> = new Vector.<Number>();
			var uvts:Vector.<Number> = new Vector.<Number>();
			var offsetZ:Number = 600;
			
			var cameraWorkX:Number = Math.sin( viewMoveX ) * 8;
			viewMoveX += 0.01;
			var cameraWorkY:Number = Math.sin( viewMoveY ) * 8 + 20;
			viewMoveY += 0.02;
			
			skirt.flutter( windPowerX, windPowerY, windPowerZ );
			
			mtx3D.identity();
			mtx3D.appendRotation( cameraWorkX, Vector3D.Y_AXIS);
			mtx3D.appendRotation( cameraWorkY, Vector3D.X_AXIS);
			mtx3D.appendTranslation( 0, 0, offsetZ );
			mtx3D.append( projectionMatrix3D );
			bugfix( mtx3D );
			
			Utils3D.projectVectors( mtx3D, skirt.vertices3D, projectedVerts, uvts );
			
			screen.graphics.clear();
			screen.graphics.lineStyle( 0, 0xFF0000 );
			//screen.graphics.beginFill( 0x993333 );
			if ( cullingFlag ) {
				screen.graphics.drawTriangles( projectedVerts, skirt.indices, null );
			} else {
				screen.graphics.drawTriangles( projectedVerts, skirt.indices, null, TriangleCulling.NEGATIVE );
			}
			//screen.graphics.endFill();
		}
		private function bugfix( matrix:Matrix3D ):void {
			var m1:Matrix3D = new Matrix3D(Vector.<Number>( [ 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 1, 0 ] ) );
			var m2:Matrix3D = new Matrix3D(Vector.<Number>( [ 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 1, 0, 0, 0, 0 ] ) );
			m1.append( m2 );
			if ( m1.rawData[15] == 20 ) {
				var rawData:Vector.<Number> = matrix.rawData;
				rawData[15] /= 20;
				matrix.rawData = rawData;
			}
		}
	}
}

class Skirt {
	public var flutter:Function;
	public var vertices3D:Vector.<Number>;
	public var indices:Vector.<int>;
	private var node:Array;
	public function Skirt() {
		var friction:Number = 0.8;
		var spring:Number = 0.04;
		var gravity:Number = 0.7;
		var rows:uint = 36;
		var cols:uint = 14;
		node = new Array( rows ).map(
			function():Array {
				return new Array( cols ).map(
					function():Object {
						return {
							px:0, py:0, pz:0,
							vx:0, vy:0, vz:0,
							mx:0, my:0, mz:0,
							fix:0
						};
					}
				);
			}
		);
		for ( var i:uint = 0; i < rows; i++ ) {
			for ( var j:uint = 0; j < cols; j++ ) {
				var radius:Number = 30 + ( j - 2 ) * 0.5;
				node[ i ][ j ].px = node[ i ][ j ].fx = Math.cos( i / rows * 6.24 ) * radius;
				node[ i ][ j ].py = node[ i ][ j ].fy = j * 1.75 - 50;
				node[ i ][ j ].pz = node[ i ][ j ].fz = Math.sin( i / rows * 6.24 ) * radius;
				
				if ( j < 2 ) {
					node[ i ][ j ].fix = 1;
					node[ i ][ j ].py = node[ i ][ j ].fy = j * 6 - 50;
				}
			}
		}
		indices = new Vector.<int>();
		for ( j = 0; j < cols - 1; j++ ) {
			for ( i = 0; i < rows; i++ ) {
				if( i != rows - 1 ) {
					indices.push( i + rows * j , i + rows * j + 1, i + rows * ( j + 1 ) );
					indices.push( i + 1 + ( rows * j ), i  + 1 + ( rows * ( j + 1 ) ),  i + ( rows * ( j + 1 ) ) );
				} else {
					indices.push( i + rows * j , rows * j, i + rows * ( j + 1 ) );
					indices.push( rows * j, rows * ( j + 1 ),  i + ( rows * ( j + 1 ) ) );
				}
			}
		}
		flutter = function( windPowerX:Number, windPowerY:Number, windPowerZ:Number ):void {
			vertices3D = new Vector.<Number>();
			for ( j = 0; j < cols; j++ ) {
				for ( i = 0; i < rows; i++ ) {
					node[ i ][ j ].mx = 0;
					node[ i ][ j ].my = 0;
					node[ i ][ j ].mz = 0;
					
					var bx:Number = node[ i ][ j ].px;
					var by:Number = node[ i ][ j ].py;
					var bz:Number = node[ i ][ j ].pz;
					if ( node[ i ][ j ].fix == 0 ) {
						node[ i ][ j ].px += node[ i ][ j - 1 ].mx;
						node[ i ][ j ].py += node[ i ][ j - 1 ].my;
						node[ i ][ j ].pz += node[ i ][ j - 1 ].mz;
						
						var vpx:Number = node[ i ][ j ].px + windPowerX + ( Math.random() * 0.4 - 0.2 );
						var vpy:Number = node[ i ][ j ].py + windPowerY + ( Math.random() * 0.4 - 0.2 );
						var vpz:Number = node[ i ][ j ].pz + windPowerZ + ( Math.random() * 0.4 - 0.2 );
						if ( vpx * vpx + vpz * vpz < 1600 ) {
							node[ i ][ j ].px = vpx;
							node[ i ][ j ].py = vpy;
							node[ i ][ j ].pz = vpz;
						}
						node[ i ][ j ].vx += ( node[ i ][ j - 1 ].px - node[ i ][ j ].px ) * spring;
						node[ i ][ j ].vy += ( node[ i ][ j - 1 ].py - node[ i ][ j ].py ) * spring;
						node[ i ][ j ].vz += ( node[ i ][ j - 1 ].pz - node[ i ][ j ].pz ) * spring;
						
						node[ i ][ j ].vx *= friction;
						node[ i ][ j ].vy *= friction;
						node[ i ][ j ].vz *= friction;
						
						node[ i ][ j ].px += node[ i ][ j ].vx;
						node[ i ][ j ].py += node[ i ][ j ].vy;
						node[ i ][ j ].pz += node[ i ][ j ].vz;
						
						var radius:Number = 0.5;
						node[ i ][ j ].px += Math.cos( i / rows * 6.24 ) * radius;
						node[ i ][ j ].py -= 0.08;
						node[ i ][ j ].pz += Math.sin( i / rows * 6.24 ) * radius;
						
						node[ i ][ j ].py += gravity;
					}
					node[ i ][ j ].mx = node[ i ][ j ].px - bx;
					node[ i ][ j ].my = node[ i ][ j ].py - by;
					node[ i ][ j ].mz = node[ i ][ j ].pz - bz;
					
					vertices3D.push( node[ i ][ j ].px, node[ i ][ j ].py, node[ i ][ j ].pz );
				}
			}
		}
	}
}