package {
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.filters.*;
import flash.geom.*;
import flash.utils.*;
import org.papervision3d.core.* ;
import org.papervision3d.core.geom.*;
import org.papervision3d.scenes.*;
import org.papervision3d.objects.*;
import org.papervision3d.cameras.*;
import org.papervision3d.materials.*;
[SWF(width="700", height="400", backgroundColor="#0")]
public class Fractal extends Sprite{
private var canvas : Sprite;
private var scene : MovieScene3D;
private var camera : Camera3D;
private var linesX:Array= new Array();
private var linesZ:Array= new Array();
private var landForm:LandForm;
private var WIDTH:int = 700;
private var HEIGHT:int = 400;
public function Fractal():void
{
stage.frameRate = 20;
stage.quality = "MEDIUM";
stage.scaleMode = "noScale";
stage.align = StageAlign.TOP_LEFT;
canvas = new Sprite();
canvas.x = WIDTH/2;
canvas.y = HEIGHT/5*4;
stage.addChild( canvas );
scene = new MovieScene3D( canvas );
var range:int = 128;
var x:int,y:int,z:int;
scene.addChild ( new Line3D([ new Vertex3D(-range,0,0), new Vertex3D(range,0,0)],
0xff0000, 0.5, 0.2));
scene.addChild( new Line3D([ new Vertex3D(0,-range,0), new Vertex3D(0,range,0)],
0xff00, 0.5, 0.2));
scene.addChild( new Line3D([ new Vertex3D(0,0,-range), new Vertex3D(0,0,range)],
0xff, 0.5, 0.2));
camera = new Camera3D();
camera.x = 100;
camera.y = 100;
camera.z = -400;
camera.focus = 100;
camera.zoom = 40;
scene.renderCamera ( camera );
landForm = new LandForm(range);
stage.addEventListener(MouseEvent.CLICK, function(e:*):void{
landForm.split();
render();
});
stage.addEventListener(MouseEvent.MOUSE_MOVE, function(e:*):void{
var rad:Number = (WIDTH/2- stage.mouseX)/WIDTH*(Math.PI)*2;
camera.x = Math.cos(rad)*100 - Math.sin(rad)*(-HEIGHT);
camera.z = Math.sin(rad)*100 + Math.cos(rad)*(-HEIGHT);
camera.zoom = Math.max((HEIGHT-stage.mouseY),30)/10 +10;
//camera.hover(0,stage.mouseX, stage.mouseY);
scene.renderCamera( camera );
});
}
private function rotateCamera(rad:Number):void{
var x:Number = camera.x;
var y:Number = camera.y;
var z:Number = camera.z;
camera.x = Math.cos(rad)*x - Math.sin(rad)*z;
//camera.y = Math.cos(rad)*x - Math.sin (rad)*z;
camera.z = Math.sin(rad)*x + Math.cos(rad)*z;
}
private function render():void
{
for(var i:int = 0 ; i < linesX.length ; i++)
scene.removeChild(linesX[i]);
for(i = 0 ; i < linesZ.length ; i++)
scene.removeChild(linesZ[i]);
for(var x:int = 0 ; x < landForm.length ; x++){
var vertexes:Array = [];
for(var z:int = 0 ; z < landForm.length ; z++){
vertexes.push(new Vertex3D(landForm.scale*(x - ( landForm.length - 1)/2),
landForm.value(x,z),
landForm.scale*(z - (landForm.length - 1)/2)));
}
var line:Line3D = new Line3D(vertexes, 0xffffff, 0.3, 0.05);
linesZ.push(line);
scene.addChild(line);
}
for(z = 0 ; z < landForm.length ; z++){
vertexes= [];
for(x = 0 ; x < landForm.length ; x++){
vertexes.push(new Vertex3D(landForm.scale*(x - (landForm.length - 1)/2),
landForm.value(x,z),
landForm.scale*(z - (landForm.length - 1)/2)));
}
line = new Line3D(vertexes, 0xffffff, 0.3, 0.05);
linesX.push(line);
scene.addChild(line);
}
trace(landForm.value(landForm.length-1, landForm.length-1));
scene.renderCamera(camera);
}
}
}
internal class LandForm{
private var buffer:Array = new Array();
private var range:int ;
private var splitCnt:int = 0;
private var base:Number = 10;
// range は2の乗数であること
public function LandForm(range:int){
this.range = range;
clear();
}
public function clear():void{
buffer = [];
// 変位が格納される2次元配列(w*h)
for(var j:int = 0 ; j < range+1; j++){
var aa:Array = new Array();
for(var k:int = 0 ; k < range+1; k++)
aa.push(0);
buffer.push(aa);
}
buffer[0][0] = base*Math.random();
buffer[range][0] = base*2*Math.random();
buffer[0][range] = base*3*Math.random();
buffer[range][range] = base*4*Math.random();
//trace(buffer[128][128]);
}
public function split():void{
if(Math.pow(2,splitCnt) >= range){
splitCnt=0;
clear();
}
splitCnt++;
for(var x:int = 1 ; x < length ; x+=2){
for(var y:int = 1 ; y < length ; y+=2){
splitMidPoint(x, y);
}
}
}
private function splitMidPoint(x:int, y:int):void{
midPoint(x,y,true);
midPoint(x-1,y);
midPoint(x+1,y);
midPoint(x,y-1);
midPoint(x,y+1);
}
private function midPoint(x:int, y:int, squere:Boolean=false):void{
//trace(x.toString() + ":" + y.toString());
var sum:Array = [];
if(squere){
if(x > 0 && y > 0 && value(x-1,y-1) != 0 )
sum.push(value(x-1, y-1));
if(x > 0 && y < length-1 && value(x-1,y+1) != 0)
sum.push(value(x-1, y+1));
if(x < length - 1 && y > 0 && value(x+1,y-1) != 0)
sum.push(value(x+1, y-1));
if(x < length - 1 && y < length - 1 && value(x+1,y+1) != 0)
sum.push(value(x+1, y+1));
}else{ // diamonds
if(y > 0 && value(x,y-1) != 0)
sum.push(value(x, y-1));
if(x > 0 && value(x-1,y) != 0)
sum.push(value(x-1, y));
if(y < length - 1 && value(x,y+1) != 0)
sum.push(value(x, y+1));
if(x < length - 1 && value(x+1,y) != 0)
sum.push(value(x+1, y));
}
var sumOfHeight:Number = 0;
for each(var v:Number in sum)
sumOfHeight += v;
var avg:Number = sumOfHeight / sum.length ;
setValue(x,y, newHeight(avg));
}
private function newHeight(avg:Number):Number{
// return avg + (Math.random()*(Math.pow(2, - 0.3*splitCnt)));
return avg*(1 + (Math.random ()*2 - 1) * scale * 0.019);
}
public function get length():int{
return Math.pow(2, splitCnt) + 1;
}
public function get scale():int{
return range / Math.pow(2,splitCnt);
}
public function value(x:int, z:int):Number{
return buffer[x*scale][z*scale];
}
private function setValue(x:int, z:int, value:Number):void{
buffer[x*scale][z*scale] = value;
}
}
Author:yamasv@gmail.com
コメント、トラックバック、リンクはお気軽に
-->
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
|---|---|---|---|---|---|---|
| - | - | - | - | - | 1 | 2 |
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 | - | - | - | - | - | - |