ball with perlin
demo for http://www.meetup.com/Budapest-Flash-Meetup-Group/
/**
* Copyright ysle ( http://wonderfl.net/user/ysle )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/7hCu
*/
package
{
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.filters.BevelFilter;
import flash.filters.DropShadowFilter;
import flash.filters.GlowFilter;
import flash.geom.ColorTransform;
import flash.geom.Matrix3D;
import flash.geom.Utils3D;
import flash.geom.Vector3D;
import flash.text.TextField;
import flash.text.TextFormat;
[SWF(width="465", height="465", backgroundColor="0x000000", frameRate="30")]
public class BallLite extends Sprite
{
private var screen:Sprite
private var radius:Number = 175
private var texture:BitmapData
private var noise:BitmapData
private var vertices:Vector.<Number>
private var indices:Vector.<int>
private var uvtData:Vector.<Number>
private var matrix3D:Matrix3D
private var projectedVertices:Vector.<Number>
private var fold:Number = 0
private var renderMode:int = 0
private var _detail:Number = 5
private var xDetail:Number = 30
private var yDetail:Number = 20
private var rx:Number = 0
private var ry:Number = 0
private var _color:Number = 0xff
private var helpTf:TextField
private var statTf:TextField
public function BallLite()
{
addChild(screen = new Sprite())
addChild(helpTf = new TextField())
addChild(statTf = new TextField())
helpTf.multiline = true
helpTf.autoSize = statTf.autoSize = 'left'
helpTf.defaultTextFormat = statTf.defaultTextFormat = new TextFormat('verdana', 10, 0xffffff)
helpTf.text = 'click : render mode\nshift + click : color\n\nup / down : detail\nleft / right : fold'
helpTf.selectable = statTf.selectable = false
helpTf.x = helpTf.y = statTf.x = 10
statTf.y = helpTf.y + helpTf.height + 10
noise = new BitmapData(400, 400, true, 0xff000000)
noise.perlinNoise(100, 100, 1, int(Math.random() * 100), true, false, 8, true)
texture = new BitmapData(400, 400, true, 0xff000000)
color = 0x00ff00
detail = 8
initGrid()
stage.align = 'TL'
stage.quality= 'LOW'
stage.scaleMode = 'noScale'
stage.addEventListener('enterFrame', render)
stage.addEventListener('mouseDown', onMouseDown)
stage.addEventListener('keyDown', onKeyDown)
stage.addEventListener('resize', onStageResize)
onStageResize()
}
private function initGrid():void
{
vertices = new Vector.<Number>()
indices = new Vector.<int>()
uvtData = new Vector.<Number>()
projectedVertices = new Vector.<Number>()
var xr:Number = 0
var yr:Number = 0
var xrd:Number = (Math.PI *2) / xDetail
var yrd:Number = Math.PI / yDetail
var i:Number
var r:Number
for (var y:Number = 0; y <= yDetail ; y++ )
{
xr = 0
for (var x:Number = 0; x <= xDetail; x++ )
{
r = radius - fold + fold * Math.random()
vertices.push
(
r * Math.sin(yr) * Math.cos(xr),
r * Math.sin(yr) * Math.sin(xr),
r * Math.cos(yr)
)
uvtData.push(x / xDetail, y / yDetail, 0)
i = y * xDetail + x + y
if (x < xDetail && y < yDetail)
{
indices.push(i, i + 1, i + xDetail + 1)
indices.push(i + 1, i + 1 + xDetail + 1, i + xDetail + 1)
}
xr += xrd
}
yr += yrd
}
statTf.text = 'vertices : ' + vertices.length
}
private function render(...e):void
{
matrix3D = new Matrix3D()
matrix3D.prependRotation( 90, Vector3D.X_AXIS)
matrix3D.appendRotation( rx += screen.mouseX / 10, Vector3D.Y_AXIS)
matrix3D.appendRotation( - screen.mouseY / 2, Vector3D.X_AXIS)
Utils3D.projectVectors(matrix3D, vertices, projectedVertices, uvtData)
screen.graphics.clear()
if (renderMode != 2 && texture) screen.graphics.beginBitmapFill(texture)
if (renderMode > 0) screen.graphics.lineStyle(0, _color, .5)
screen.graphics.drawTriangles(projectedVertices, indices, uvtData, 'negative')
}
public function get color():Number { return _color }
public function set color(value:Number):void
{
_color = value
texture.fillRect(texture.rect, 0x00000000)
texture.draw(noise, null, new ColorTransform((_color >> 16) / 0xff, (_color >> 8 & 0xff) / 0xff, (_color & 0xff) / 0xff, 1), null, noise.rect, false)
screen.filters =
[
new DropShadowFilter(0, 0, _color, 1, 4, 4, 1, 3, false),
new GlowFilter(_color, 1, 20, 20, 2, 3, false),
new BevelFilter(radius / 2, 45, 0xffffff, .5, 0, 1, radius / 2, radius / 2, 1, 3)
]
}
public function get detail():Number { return _detail }
public function set detail(value:Number):void
{
xDetail = 3 * (_detail = value)
yDetail = 2 * _detail
}
private function onMouseDown(e:MouseEvent):void
{
if (e.shiftKey) color = Math.random() * 0xffffff
else if (renderMode++ > 1) renderMode = 0
}
private function onKeyDown(e:KeyboardEvent):void
{
switch(e.keyCode)
{
case 37: fold = Math.min(100, fold +10 ); break
case 39: fold = Math.max(0, fold -10 ); break
case 38: detail = Math.min(20, _detail + 1); break
case 40: detail = Math.max(1, _detail - 1); break
default : return
}
initGrid()
}
private function onStageResize(...e):void
{
screen.x = stage.stageWidth / 2
screen.y = stage.stageHeight / 2
}
}
}