3D Cellular Automata
/**
* Copyright greentec ( http://wonderfl.net/user/greentec )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/ionO
*/
package
{
import away3d.cameras.Camera3D;
import away3d.containers.Scene3D;
import away3d.containers.View3D;
import away3d.controllers.HoverController;
import away3d.debug.AwayStats;
import away3d.entities.Mesh;
import away3d.materials.ColorMaterial;
import away3d.primitives.CubeGeometry;
import flash.display.*;
import flash.events.Event;
import flash.events.MouseEvent;
import away3d.lights.DirectionalLight;
import away3d.materials.lightpickers.StaticLightPicker;
/**
* ...
* @author ypc
*/
public class Main extends Sprite
{
private var view:View3D;
private var scene:Scene3D;
private var camera:Camera3D;
private var awayStats:AwayStats;
private var cameraController:HoverController;
private var light:DirectionalLight;
private var lightPicker:StaticLightPicker;
private var cubeMX:int = 4;
private var cubeMY:int = 4;
private var cubeMZ:int = 4;
private var cubeArray:Array = [];
//navigation variables
private var move:Boolean = false;
private var lastPanAngle:Number;
private var lastTiltAngle:Number;
private var lastMouseX:Number;
private var lastMouseY:Number;
private var cubeNumberVector:Vector.<Vector.<Vector.<int>>> = new Vector.<Vector.<Vector.<int>>>(cubeMZ * 2 + 1);
private var neighborNumberVector:Vector.<Vector.<Vector.<int>>> = new Vector.<Vector.<Vector.<int>>>(cubeMZ * 2 + 1);
private var runCount:int = 0;
//private var source:BitmapData = new BitmapData(465, 465, false, 0x000000);
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
Wonderfl.disable_capture();
//addChild(new Bitmap(source));
initEngine();
initLight();
initObject();
initListener();
}
private function initLight():void
{
light = new DirectionalLight( -0.5, -1, -1);
light.color = 0xffffff;
light.ambient = 1;
scene.addChild(light);
lightPicker = new StaticLightPicker([light]);
}
private function initEngine():void
{
view = new View3D();
view.antiAlias = 4;
scene = view.scene;
camera = view.camera;
camera.lens.far = 5000;
cameraController = new HoverController(camera);
cameraController.distance = 500;
cameraController.panAngle = 45;
cameraController.tiltAngle = 20;
awayStats = new AwayStats(view);
}
private function initObject():void
{
var i:int;
var j:int;
var k:int;
var cube:Mesh;
var cubeGeometry:CubeGeometry = new CubeGeometry(30, 30, 30, 1, 1, 1, false);
var cubeMaterial:ColorMaterial;
var color:int;
for (i = -cubeMX; i <= cubeMX; i += 1)
{
cubeArray[i + cubeMX] = [];
cubeNumberVector[i + cubeMX] = new Vector.<Vector.<int>>(2 * cubeMZ + 1);
neighborNumberVector[i + cubeMX] = new Vector.<Vector.<int>>(2 * cubeMZ + 1);
for (j = -cubeMY; j <= cubeMY; j += 1)
{
cubeArray[i + cubeMX][j + cubeMY] = [];
cubeNumberVector[i + cubeMX][j + cubeMY] = new Vector.<int>(2 * cubeMZ + 1);
neighborNumberVector[i + cubeMX][j + cubeMY] = new Vector.<int>(2 * cubeMZ + 1);
for (k = -cubeMZ; k <= cubeMZ; k += 1)
{
cubeMaterial = new ColorMaterial();
cubeMaterial.lightPicker = lightPicker;
color = (127 + int(Math.random() * 127) - 63);
//cubeMaterial.color = (204 + int(Math.random() * 20) - 10) << 16 | (204 + int(Math.random() * 20) - 10) << 8 | (204 + int(Math.random() * 20) - 10);
cubeMaterial.color = color << 16 | color << 8 | color;
cubeMaterial.ambient = 0.1;
cubeMaterial.specular = 0.2;
cube = new Mesh(cubeGeometry, cubeMaterial);
cube.x = i * 40;
cube.y = j * 40;
cube.z = k * 40;
scene.addChild(cube);
cubeArray[i + cubeMX][j + cubeMY].push(cube);
cube.visible = false;
cubeNumberVector[i + cubeMX][j + cubeMY][k + cubeMZ] = 0;
neighborNumberVector[i + cubeMX][j + cubeMY][k + cubeMZ] = 0;
}
}
}
for (i = -2; i <= 2; i += 1) //initial setting
{
cubeArray[cubeMX][cubeMY][cubeMZ + i].visible = true;
cubeNumberVector[cubeMX][cubeMY][cubeMZ + i] = 1;
}
}
private function initListener():void
{
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
stage.addEventListener(Event.RESIZE, resizeHandler);
addEventListener(Event.ENTER_FRAME, render);
addChild(view);
addChild(awayStats);
}
private function render(e:Event):void
{
if (move)
{
cameraController.panAngle = 0.3 * (stage.mouseX - lastMouseX) + lastPanAngle;
cameraController.tiltAngle = 0.3 * (stage.mouseY - lastMouseY) + lastTiltAngle;
}
runCount += 1;
if (runCount % 30 == 0)
{
var i:int;
var j:int;
var k:int;
var lenX:int = cubeMX * 2 + 1;
var lenY:int = cubeMY * 2 + 1;
var lenZ:int = cubeMZ * 2 + 1;
var countNeighbor:int;
for (i = 0; i < lenX; i += 1)
{
for (j = 0; j < lenY; j += 1)
{
for (k = 0; k < lenZ; k += 1)
{
countNeighbor = 0;
if (i > 1)
{
countNeighbor += cubeNumberVector[i - 1][j][k];
}
if (i < lenX - 1)
{
countNeighbor += cubeNumberVector[i + 1][j][k];
}
if (j > 1)
{
countNeighbor += cubeNumberVector[i][j - 1][k];
}
if (j < lenY - 1)
{
countNeighbor += cubeNumberVector[i][j + 1][k];
}
if (k > 1)
{
countNeighbor += cubeNumberVector[i][j][k - 1];
}
if (k < lenZ - 1)
{
countNeighbor += cubeNumberVector[i][j][k + 1];
}
neighborNumberVector[i][j][k] = countNeighbor;
}
}
}
for (i = 0; i < lenX; i += 1)
{
for (j = 0; j < lenY; j += 1)
{
for (k = 0; k < lenZ; k += 1)
{
if (cubeNumberVector[i][j][k] == 0) //off -> 1-3: on
{
if (neighborNumberVector[i][j][k] >= 1 && neighborNumberVector[i][j][k] < 5)
{
cubeNumberVector[i][j][k] = 1;
cubeArray[i][j][k].visible = true;
}
}
else //on -> 3-6: off
{
if (neighborNumberVector[i][j][k] >= 3)
{
cubeNumberVector[i][j][k] = 0;
cubeArray[i][j][k].visible = false;
}
}
}
}
}
}
view.render();
//view.renderer.queueSnapshot(source);
}
private function onMouseDown(e:MouseEvent):void
{
lastPanAngle = cameraController.panAngle;
lastTiltAngle = cameraController.tiltAngle;
lastMouseX = stage.mouseX;
lastMouseY = stage.mouseY;
move = true;
}
private function onMouseUp(e:MouseEvent):void
{
move = false;
}
private function resizeHandler(e:Event):void
{
view.width = stage.stageWidth;
view.height = stage.stageHeight;
}
}
}