forked from: soundSpectrumCity
/**
* Copyright h_sakurai ( http://wonderfl.net/user/h_sakurai )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/KSSS
*/
// forked from zonnbe's soundSpectrumCity
package
{
import flash.display.*;
import flash.events.*;
import flash.utils.*;
import flash.geom.*;
[SWF(width=465,height=465,backgroundColor=0x000000,frameRate=30)]
public class therockcityMAX extends Sprite
{
//planning
private var regions:Array = new Array();
private var gCount:int = 300;
private var gwidth:int = 1000;//stage.stageWidth;
private var gheight:int = 1000;//stage.stageHeight;
//building
private var blength:Number = 100;
private var bwidth:Number = 200;
private var bheight:Number = 200;
private var offset:Dot = new Dot(-gwidth/2, -gheight/2);
//////////////////////////////////////////////////////////////////////////////////////////////////
// drawTriangles
//////////////////////////////////////////////////////////////////////////////////////////////////
private var viewport:Shape = new Shape();
private var world:Matrix3D = new Matrix3D();
private var vertices:Vector.<Number> = new Vector.<Number>(0, false);
private var projected:Vector.<Number> = new Vector.<Number>(0, false);
private var indices:Vector.<int> = new Vector.<int>(0, false);
private var uvtData:Vector.<Number> = new Vector.<Number>(0, false);
private var projection:PerspectiveProjection = new PerspectiveProjection();
private var sortedIndices:Vector.<int>;
private var faces:Array = [];
/**/
/////////////////////////////////////////////////////////////////////////////////////////////////
private var rotate:Number = 0;
/////////////////////////////////////////////////////////////////////////////////////////////////
private var bitmapData:BitmapData = new BitmapData(500,500, false, 0xFF220000);
private var m:Matrix = new Matrix();
private var windowX:int = 32;
private var windowY:int = 16;
[SWF(width=465,height=465,backgroundColor=0x000011,frameRate=60)]
public function therockcityMAX() {
m.translate(stage.stageWidth/2, stage.stageHeight-130);
regions.push(new Region);
regions[0].vertices.push(new Dot(0 ,0));
regions[0].vertices.push(new Dot(gwidth, 0));
regions[0].vertices.push(new Dot(gwidth, gheight));
regions[0].vertices.push(new Dot(0, gheight));
viewport.x = stage.stageWidth / 2;
viewport.y = stage.stageHeight / 2;
addChild(viewport);
projection.fieldOfView = 45;
//planning
generateCity();
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
var size:Number = bitmapData.width*0.8;
for(var i:int = 0; i < 512; i++) {
bitmapData.fillRect(
new Rectangle(
(i%windowX)*(size/windowX),
int(i/windowX)*(size/windowY),
(size/windowX)-8, (size/windowY)-8), 0xFFFFCC32);
}
}
private function onEnterFrame(e:Event):void
{
world.identity();
rotate +=2;
world.appendRotation(rotate, Vector3D.Y_AXIS);
world.appendRotation(30, Vector3D.X_AXIS);
world.appendTranslation(0, 220, 1000);
world.append(projection.toMatrix3D());
Utils3D.projectVectors(world, vertices, projected, uvtData);
resort();
viewport.graphics.clear();
viewport.graphics.beginBitmapFill(bitmapData, null, false, false);
viewport.graphics.drawTriangles(projected, sortedIndices, uvtData, TriangleCulling.NEGATIVE);
viewport.graphics.endFill();
/**/
}
private function resort():void {
var face:Vector3D;
var inc:int = 0;
var i1:uint = 0x0;
var i2:uint = 0x0;
var i3:uint = 0x0;
var i4:int = 0;
for (var i:int = 0; i<indices.length; i+=3){
i1 = indices[ i+0 ];
i2 = indices[ i+1 ];
i3 = indices[ i+2 ];
face = faces[inc];
face.x = i1;
face.y = i2;
face.z = i3;
face.w = (uvtData[i1 * 3 + 2] + uvtData[i2 * 3 + 2] + uvtData[i3 * 3 + 2])
inc++;
}
faces.sortOn("w", Array.NUMERIC);
inc = 0;
for each (face in faces){
sortedIndices[inc++] = face.x;
sortedIndices[inc++] = face.y;
sortedIndices[inc++] = face.z;
}
}
private function generateCity():void {
var i:int = 0;
var j:int = 0;
var k:int = 0;
var randomlyPick:int = 0;
var randomlyRatio:Number = 0;
var rFactor:int = 1
var rFrom:int = 2;
var rTo:int = 3;
var limitLength:Number = 10;
var limitSize:Number = 3000;
var align:Boolean = true;
var detectLongest:Boolean = true;
var aRFactor:int = 1;
while(i<gCount)
{
randomlyPick = int(multipleRandom(rFactor) * regions.length);
randomlyRatio = rFrom+Math.round(multipleRandom(rFactor) * (rTo - rFrom));
if(regions[randomlyPick].pass)
{
if(regions[randomlyPick].needPush2Region(
regions,
1/randomlyRatio,
limitLength, limitSize, align, detectLongest, false, aRFactor))
{
regions.splice(randomlyPick,1);
}
}
i++;
}
var tempvertices:Array = new Array();
for(i = 0; i < regions.length; i++)
{
regions[i].getResizedRegionVerticesByRatio(tempvertices, 0.7);
constructBuildingByVertices(tempvertices, m);
tempvertices.splice(0, tempvertices.length);
regions[i].getResizedRegionVerticesByRatio(tempvertices, 0.9);
tempvertices.splice(0, tempvertices.length);
}
}
private function constructBuildingByVertices(va:Array, m:* = null):void
{
var i:int = 0;
var j:int = 0;
var min:Number = bheight*0.20;
var max:Number = bheight*0.80;
var randomlyHeight:Number = min+multipleRandom(2)*max;
var i1:uint = 0;
var i2:uint = 0;
var i3:uint = 0;
var i4:uint = 0;
var indexer:int = 0;
var vratio:Number = 0.8;
for(i = 0; i < va.length; i++)
{
j = (i+1)%va.length;
indexer = vertices.length/3;
vertices.push(va[i].x+offset.x, -randomlyHeight, va[i].y+offset.y); //TL
vertices.push(va[j].x+offset.x, -randomlyHeight, va[j].y+offset.y); //TR
vertices.push(va[i].x+offset.x, 0, va[i].y+offset.y); //BL
vertices.push(va[j].x+offset.x, 0, va[j].y+offset.y); //BR
uvtData.push(0+i*vratio/4, 0, 0); //1
uvtData.push((i+1)*vratio/4, 0, 0); //2
uvtData.push(0+i*vratio/4, vratio, 0); //3
uvtData.push((i+1)*vratio/4, vratio, 0); //4
/**/
i1 = indexer;
i2 = indexer + 1;
i3 = indexer + 2;
i4 = indexer + 3;
indices.push(i1, i2, i3, i3, i2, i4);
faces.push(new Vector3D(), new Vector3D());
}
/**/
indexer = vertices.length/3;
// top
vertices.push(va[1].x+offset.x, -randomlyHeight, va[1].y+offset.y); //TL
vertices.push(va[0].x+offset.x, -randomlyHeight, va[0].y+offset.y); //TR
vertices.push(va[2].x+offset.x, -randomlyHeight, va[2].y+offset.y); //BL
vertices.push(va[3].x+offset.x, -randomlyHeight, va[3].y+offset.y); //BR
uvtData.push(vratio, vratio, 0); //1
uvtData.push(1, vratio, 0); //2
uvtData.push(vratio, 1, 0); //3
uvtData.push(1, 1, 0); //4
i1 = indexer;
i2 = indexer + 1;
i3 = indexer + 2;
i4 = indexer + 3;
indices.push(i1, i2, i3, i3, i2, i4);
faces.push(new Vector3D(), new Vector3D());
/**/
//if(!sortedIndices)
sortedIndices= new Vector.<int>(indices.length, true);
}
private function multipleRandom(factor:int):Number
{
var counter:int = 0;
var rand:Number = 1;
while(counter++<factor) {
rand *= Math.random();
}
return rand;
}
private function area(p:Array):Number
{
var i:int = 0;
var j:int = 0;
var a:Number = 0;
i = 0;
while (i < p.length)
{
j = (i + 1) % p.length;
a = a + p[i].x * p[j].y;
a = a - p[i].y * p[j].x;
i++;
}
a = a / 2;
return a;
}
}
}
import flash.display.*;
import flash.text.*;
import flash.events.*;
import flash.display.Sprite;
import flash.net.*;
import flash.filters.*;
import flash.geom.*;
import flash.ui.*;
class Region
{
public var vertices:Array = new Array();
public var pass:Boolean = true;
// right is always equal to edge index, so skip the right function
public function getVerticeAtEdgeLeft(index:int):int
{
return (index+1>3)?0:index+1;
}
public function getOppositeEdgeOfEdge(index:int):int
{
return (index+2>3)?(index+2)%4:index+2;
}
public function needPush2Region(origin:Array, ratio:Number, limitLength:Number = 0.0, limitSize:Number = 0.0, align:Boolean = true, detectLongest:Boolean = true, randomAlign:Boolean = false, aRFactor:int = 1):Boolean
{
var rIndex:int = int(Math.random() * 4);
if(detectLongest)
rIndex = getLongestEdgeStartFromEdge(rIndex);
var rLeft:int = getVerticeAtEdgeLeft(rIndex);
var rRight:int = rIndex;
var vx:Number = vertices[rLeft].x - vertices[rRight].x;
var vy:Number = vertices[rLeft].y - vertices[rRight].y;
var vlen:Number = Math.sqrt(vx*vx+vy*vy);
if(limitLength == 0.0 || vlen>limitLength)
{
var oIndex:int = getOppositeEdgeOfEdge(rIndex);
var oLeft:int = getVerticeAtEdgeLeft(oIndex);
var oRight:int = oIndex;
var rPoint:Dot;
rPoint = getPointAtEdgeByRatio(rIndex, ratio);
var oPoint:Dot = getPointAtEdgeByRatio(oIndex, 1-ratio);
var regionLeft:Region = new Region();
var regionRight:Region = new Region();
regionLeft.vertices.push(vertices[oRight].clone());
regionLeft.vertices.push(oPoint);
regionLeft.vertices.push(rPoint);
regionLeft.vertices.push(vertices[rLeft].clone());
if(limitSize != 0.0 && regionLeft.area()<limitSize)
{
regionLeft.pass = false;
}
origin.push(regionLeft);
regionRight.vertices.push(oPoint);
regionRight.vertices.push(vertices[oLeft].clone());
regionRight.vertices.push(vertices[rRight].clone());
regionRight.vertices.push(rPoint);
if(limitSize != 0.0 && regionRight.area()<limitSize)
{
regionRight.pass = false;
}
origin.push(regionRight);
return true;
}
return false;
}
public function getPointAtEdgeByRatio(index:int, ratio:Number):Dot
{
var jndex:int = (index+1)%4;
var vx:Number = vertices[jndex].x - vertices[index].x;
var vy:Number = vertices[jndex].y - vertices[index].y;
return new Dot(vertices[index].x+vx*ratio, vertices[index].y+vy*ratio);
}
public function getLengthOfEdge(index:int):Number
{
var nextIndex:int = (index+1)%4;
var vx:Number = vertices[nextIndex].x - vertices[index].x;
var vy:Number = vertices[nextIndex].y - vertices[index].y;
return Math.sqrt(vx*vx+vy*vy);
}
public function getLongestEdgeStartFromEdge(index:int):int
{
var li:int = index;
var ci:int = index;
var startIndex:int = index;
var longestLength:Number = getLengthOfEdge(index);
var currLength:Number = 0;
do{
ci = (ci+1)%4;
currLength = getLengthOfEdge(ci);
if(currLength>longestLength)
{
longestLength = currLength;
li = ci;
}
} while(ci != startIndex);
return li;
}
public function area():Number
{
var i:int = 0;
var j:int = 0;
var a:Number = 0;
i = 0;
while (i < vertices.length)
{
j = (i + 1) % vertices.length;
a = a + vertices[i].x * vertices[j].y;
a = a - vertices[i].y * vertices[j].x;
i++;
}
a = a / 2;
return a;
}
public function multipleRandom(factor:int):Number
{
var counter:int = 0;
var rand:Number = 1;
while(counter++<factor)
{
rand *= Math.random();
}
return rand;
}
public function pdis(a:Dot, b:Dot, c:Dot):Number
{
var t:Dot = new Dot(b.x-a.x, b.y-a.y);// # Vector ab
var dd:Number = Math.sqrt(t.x*t.x+t.y*t.y);// # Length of ab
t.val_p_(t.x/dd, t.y/dd);// # unit vector of ab
var n:Dot = new Dot(-t.y, t.x);// # normal unit vector to ab
var ac:Dot = new Dot(c.x-a.x, c.y-a.y);// # vector ac
return Math.abs(ac.x*n.x+ac.y*n.y);
}
public function com() : Dot// centre of mass
{
var cm:Dot = new Dot(0, 0);
var tx:Number = 0;
var ty:Number = 0;
var a:Number = area();
var i:int = 0;
var j:int = 0;
var d:Number = 0;
i = 0;
while (i < vertices.length)
{
j = (i + 1) % vertices.length;
d = vertices[i].x * vertices[j].y - vertices[j].x * vertices[i].y;
tx = tx + (vertices[i].x + vertices[j].x) * d;
ty = ty + (vertices[i].y + vertices[j].y) * d;
i++;
}
a = a * 6;
d = 1 / a;
tx = tx * d;
ty = ty * d;
cm.x = tx;
cm.y = ty;
return cm;
}
public function getResizedRegionVerticesByRatio(target:Array, ratio:Number = 1.0):void
{
var centerOfMass:Dot = com();
var vx:Number = 0;
var vy:Number = 0;
var i:int = 0;
for(i = 0; i < vertices.length; i++)
{
vx = vertices[i].x - centerOfMass.x;
vy = vertices[i].y - centerOfMass.y;
target.push(new Dot(centerOfMass.x+vx*ratio, centerOfMass.y+vy*ratio));
}
}
}
class Dot
{
public var x:Number = 0;
public var y:Number = 0;
public var tx:Number = 0;
public var ty:Number = 0;
public var vx:Number = 0;
public var vy:Number = 0;
public var angle:Number = 0;
public var size:Number = 0;
public var speed:Number = 0;
public var m:Number = 0;
public var rad:Number = 0;
public function Dot(px:Number,py:Number)
{
x = px;
y = py;
tx = x;
ty = y;
}
public function clone():Dot
{
return new Dot(this.x, this.y);
}
public function val_(p:Dot):Dot
{
x = p.x;
y = p.y;
return this;
}
public function val_p_(px:Number, py:Number):Dot
{
x = px;
y = py;
return this;
}
public function add_(px:Number, py:Number):Dot
{
x += px;
y += py;
return this;
}
}