Wave simulation
perlin noise で波を表現.動かさないで眺めたほうがいいかも?
//perlin noise で波を表現.動かさないで眺めたほうがいいかも?
package {
import caurina.transitions.Tweener;
import flash.display.*;
import flash.events.*;
import flash.geom.Point;
import flash.net.*;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import flash.utils.getTimer;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.core.clipping.FrustumClipping;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.*;
import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
[SWF(backgroundColor=0xAAAAFF)]
public class WaveSimulation extends Sprite
{
//private var container : Sprite;
private var viewport : Viewport3D;
private var scene : Scene3D;
private var camera : Camera3D;
private var rootNode : DisplayObject3D;
private var renderer : BasicRenderEngine;
private var light : PointLight3D;
//for debug
private var frameCount : Number;
private var prevTimer : Number;
private var debugText : Array;
private var numDebugItems : int = 13;
//camera
private var exCamera : Array;
private var cameraStatus : int = 0; // 0: ground, 1:during change, 2:bird-eyes, 3:Look-at-paperPlane, 4:jump
private var maxFar : int = 1000;
//for wave perlin noise
private var bmpSheet : BitmapData;
private var px1 : Number = 0;
private var courseMap : DisplayObject3D;
//ground field
private var fieldObj : DisplayObject3D;
private var fieldSize : int = 2000;
private var fieldSegment : int = 10;
private var fieldMat : BitmapMaterial;
//private var fieldMat : WireframeMaterial;
private var fieldLimit : int = fieldSize / 2 - 20;
private var rightKey : Boolean = false;
private var leftKey : Boolean = false;
private var upKey : Boolean = false;
private var downKey : Boolean = false;
private var zKey : Boolean = false;
private var spaceKey : Boolean = false;
private var shiftKey : Boolean = false;
private var charaHeight : int = 50;
private var deltaRot : int = 2;
private var deltaMove : int = 7;
public function WaveSimulation( ):void
{
stage.frameRate = 30;
stage.quality = "LOW";
stage.scaleMode = "noScale";
stage.align = StageAlign.TOP_LEFT;
viewport = new Viewport3D( 0, 0, true );
renderer = new BasicRenderEngine( );
scene = new Scene3D( );
rootNode = new DisplayObject3D( );
light = new PointLight3D( );
addChild( viewport );
scene.addChild( rootNode );
renderer.clipping = new FrustumClipping( FrustumClipping.BOTTOM );
light.y = 2000;
initializeDebugger( );
bmpSheet = new BitmapData( 40, 40, false, 0 );
courseMap = new DisplayObject3D;
//create ground field
fieldMat = new BitmapMaterial( bmpSheet );
//fieldMat = new WireframeMaterial( 0xFFFFFF );
fieldMat.oneSide = false;
fieldObj = new Plane( fieldMat, fieldSize, fieldSize, fieldSegment, fieldSegment );
fieldObj.rotationX = 90;
courseMap.addChild( fieldObj );
/* create object you want */
for( var i:int = -1; i < 2; i++ )
{
for( var j:int = -1; j < 2; j++ )
{
var coneMat:FlatShadeMaterial = new FlatShadeMaterial( light, 0xFFFF00, 0xDDDD00 );
var coneObj:Cone = new Cone( coneMat, 50, 400, 4, 1 );
coneObj.x = i * 800;
coneObj.z = j * 800;
coneObj.y = 0;
courseMap.addChild( coneObj );
}
}
rootNode.addChild( courseMap );
//camera setting
camera = new Camera3D(90, 10, maxFar, true);
camera.x = 0;
camera.y = charaHeight;
camera.z = 0;
camera.focus = 10;
camera.zoom = 50;
camera.rotationY = 300 ;
exCamera = new Array();
//fps computing
frameCount = 0;
prevTimer = getTimer();
stage.addEventListener( Event.ENTER_FRAME, loop );
stage.addEventListener( KeyboardEvent.KEY_DOWN, keyDownHandler );
stage.addEventListener( KeyboardEvent.KEY_UP, keyUPHandler );
}
private function initializeDebugger():void
{
debugText = new Array();
var debugTextFormat:TextFormat = new TextFormat();
debugTextFormat.size = 11;
debugTextFormat.color = 0xFFFFFF;
debugTextFormat.font = "Courier New";
for( var i:int = 0; i < numDebugItems; i++ )
{
debugText[ i ] = new TextField();
debugText[ i ].type = "dynamic";
debugText[ i ].width = 150;
debugText[ i ].height = 20;
debugText[ i ].x = 12;
debugText[ i ].y = 8 + 15 * i;
debugText[ i ].defaultTextFormat = debugTextFormat;
//debugText[ i ].text = " --------";
addChild( debugText[i] );
}
}
private function keyDownHandler( event:KeyboardEvent ):void
{
switch ( event.keyCode )
{
case Keyboard.RIGHT:
rightKey = true;
break;
case Keyboard.LEFT:
leftKey = true;
break;
case Keyboard.UP:
upKey = true;
break;
case Keyboard.DOWN:
downKey = true;
break;
case 90: // Z key
zKey = true;
break;
case Keyboard.SPACE:
spaceKey = true;
break;
case Keyboard.SHIFT:
shiftKey = true;
break;
default:
break;
}
}
private function keyUPHandler( event:KeyboardEvent ):void
{
switch ( event.keyCode )
{
case Keyboard.RIGHT:
rightKey = false;
break;
case Keyboard.LEFT:
leftKey = false;
break;
case Keyboard.UP:
upKey = false;
break;
case Keyboard.DOWN:
downKey = false;
break;
case 90:
zKey=false;
break;
case Keyboard.SPACE:
spaceKey = false;
break;
case Keyboard.SHIFT:
shiftKey = false;
break;
default:
break;
}
}
private function loop( event:Event ):void
{
waveMotion();
controlCamera();
displayDebug();
renderer.renderScene( scene, camera, viewport );
}
private function waveMotion():void
{
var camPoint:Point = new Point( camera.x, camera.z );
var minDis:Array = new Array(); //Number = -1;
var minDistance:Number = -1;
var minFaceIndex:int = -1;
bmpSheet.perlinNoise(20,20,3,6,true,true,1|2|4,false,[new Point(px1+=0.3,0),new Point(-px1/2,0),new Point(0,0)]);
for(var i:int = 0; i < fieldObj.geometry.vertices.length; i++ )
{
var px:int = int( i / (fieldSegment+1) );
var py:int = i % (fieldSegment+1);
var pixelVal:uint = bmpSheet.getPixel( px, py );
var blueVal:uint = pixelVal & 0xFF;
fieldObj.geometry.vertices[i].z = ( blueVal - 128 ) * 2;
}
for( i = 0; i < fieldObj.geometry.faces.length; i++ )
{
if( fieldObj.geometry.faces[i].v0.x - camPoint.x > fieldSize / fieldSegment ) continue;
var sumDis:Number = 0;
for( var j:int = 0; j < 3; j++ )
{
var vertexPoint:Point = new Point( fieldObj.geometry.faces[i].vertices[j].x, fieldObj.geometry.faces[i].vertices[j].y);
sumDis += Point.distance( vertexPoint, camPoint );
}
if(minDistance < 0 || minDistance > sumDis )
{
minDistance = sumDis;
minFaceIndex = i;
}
}
minDis = fieldObj.geometry.faces[minFaceIndex].vertices;
bmpSheet.lock();
for( var p:int = 0; p < bmpSheet.width; p++ )
{
for( var q:int = 0; q < bmpSheet.height; q++ )
{
var pixelValue:uint = bmpSheet.getPixel( p, q );
var red:uint = int( (pixelValue >> 16 & 0xFF).toString() ) /1.5 ;
var green:uint = int( (pixelValue >> 8 & 0xFF).toString() ) /1.5 ;
//var blue:uint = pixelValue & 0xFF;
var newColor:uint = red << 16 | green << 8 | 255;
bmpSheet.setPixel( p, q, newColor );
}
}
bmpSheet.unlock();
if(cameraStatus == 0) //camera.y = - meanHeight + 40;
{
var triPlane:DisplayObject3D = new DisplayObject3D();
var tri3D:Triangle3D = new Triangle3D( triPlane, minDis );
camera.y = 40 - minDis[0].z + ( tri3D.faceNormal.x * ( camera.x - minDis[0].x ) + tri3D.faceNormal.y * ( camera.z - minDis[0].y ) ) / tri3D.faceNormal.z;
}
}
private function controlCamera():void
{
camera.rotationY = ( camera.rotationY + 360 ) % 360;
camera.rotationX = ( camera.rotationX + 360 ) % 360;
camera.rotationZ = ( camera.rotationZ + 360 ) % 360;
if( spaceKey == true )
{
if( cameraStatus == 0 ) // on normal mode
{
camera.far = 3000;
renderer.clipping = new FrustumClipping(FrustumClipping.NEAR);
cameraStatus = 1; // on changing modes
exCamera[0] = camera.x;
exCamera[1] = camera.y;
exCamera[2] = camera.z;
exCamera[3] = camera.rotationX;
exCamera[4] = camera.rotationY;
exCamera[5] = camera.rotationZ;
Tweener.addTween( camera, {x: 1000, y:2000, z:1000, time:2} );
Tweener.addTween( camera, {rotationX: 60, rotationY: 220, time:3, onComplete: function():void{cameraStatus = 2} } );
}
else if( cameraStatus == 2 ) // on birds-eye mode
{
camera.far = maxFar;
cameraStatus = 1;
courseMap.rotationY = 0;
Tweener.addTween( camera, {x: exCamera[0], y:exCamera[1], z:exCamera[2], time:3} );
Tweener.addTween( camera, {rotationX: exCamera[3], rotationY: exCamera[4], time:2, onComplete: function():void
{
cameraStatus = 0;
renderer.clipping = new FrustumClipping(FrustumClipping.BOTTOM);
}} );
exCamera.length = 0;
}
}
if( rightKey == true )
{
if( cameraStatus == 0 )
{
camera.rotationY += deltaRot;
}
else if( cameraStatus == 2 )
{
courseMap.rotationY += deltaRot;
}
}
else if( leftKey == true )
{
if( cameraStatus == 0 )
{
camera.rotationY -= deltaRot;
}
else if( cameraStatus == 2 )
{
courseMap.rotationY -= deltaRot;
}
}
if( cameraStatus == 0 )
{
if( camera.x > - fieldLimit && camera.x < fieldLimit && camera.z > - fieldLimit && camera.z < fieldLimit )
{
if( upKey == true )
{
camera.moveForward( deltaMove );
}
else if ( downKey == true )
{
camera.moveBackward( deltaMove );
}
}
}
//avoid camera going out of the field
if( camera.x > fieldLimit - deltaMove )
{
camera.x = fieldLimit - deltaMove;
}
else if( camera.x < - fieldLimit + deltaMove)
{
camera.x = - fieldLimit + deltaMove;
}
else if( camera.z > fieldLimit - deltaMove )
{
camera.z = fieldLimit - deltaMove;
}
else if( camera.z < - fieldLimit + deltaMove )
{
camera.z = - fieldLimit + deltaMove;
}
}
private function displayDebug():void
{
frameCount ++;
if ( (getTimer() - prevTimer ) / 1000 >= 0.25 )
{
var fps:Number = frameCount * 1000 / ( getTimer() - prevTimer );
fps = Math.floor( fps * 10 ) / 10;
prevTimer = getTimer();
frameCount = 0;
debugText[ 0 ].text = "FPS : " + fps;
}
debugText[ 1 ].text = "Move : ↑↓";
debugText[ 2 ].text = "Turn : →←";
debugText[ 3 ].text = "Bird-eyes: Space";
/*
debugText[ 4 ].text = "Observe : Z";
//debugText[ 5 ].text = "Jump : Shift" ;
debugText[ 7 ].text = "CAMERA_X : " + int( camera.x );
debugText[ 8 ].text = "CAMERA_Y : " + int( camera.y );
debugText[ 9 ].text = "CAMERA_Z : " + int( camera.z );
debugText[ 10 ].text = "ROT_X : " + int( camera.rotationX );
debugText[ 11 ].text = "ROT_Y : " + int( camera.rotationY );
debugText[ 12 ].text = "ROT_Z : " + int( camera.rotationZ );
*/
}
}
}