Planet Harmony
Color research for 3d planet generator.
http://3dflashlo.free.fr/planet/index.html
/**
* Copyright loth_2013 ( http://wonderfl.net/user/loth_2013 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/pxmI
*/
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Shape;
import flash.display.SimpleButton;
import flash.display.StageQuality;
import flash.display.StageAlign;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Vector3D;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.geom.Point;
import flash.filters.ColorMatrixFilter;
import flash.geom.ColorTransform;
import flash.filters.BlurFilter;
import flash.filters.GlowFilter;
import flash.filters.BevelFilter;
public class FlashTest extends Sprite {
private const GOLD:Number = 1.618;
private var _display:Bitmap;
private var _canvas:BitmapData;
private var _txt:TextField;
private var _groundColors:Vector.<uint>;
private var _skyColors:Vector.<uint>;
public function FlashTest() {
var c:Shape = new Shape();
c.graphics.beginFill(0x808080);
c.graphics.drawRect(0, 0, 465, 465);
c.graphics.endFill();
addChild(c);
_canvas = new BitmapData(360, 360, false, 0x000000);
_display = new Bitmap(_canvas);
addChild(_display);
_display.x = _display.y = 52;
var v:Vector.<SimpleButton> = new Vector.<SimpleButton>();
v[0] = button(360 + 52 + 2, 52, "Linear", 48);
v[1] = button(360 + 52 + 2, 52 + 32, "Radial", 48);
v[2] = button(52, 362 + 52, "Triad", 70, 30);
v[3] = button(52 + 72, 362 + 52, "Analogous", 86, 30);
v[4] = button(52 + 72 + 88, 362 + 52, "Monochrome", 86, 30);
v[5] = button(52 + 72 + 88 + 88, 362 + 52, "Complementary", 112, 30);
v[0].addEventListener(MouseEvent.CLICK, drawLinear);
v[1].addEventListener(MouseEvent.CLICK, drawRadial);
v[2].addEventListener(MouseEvent.CLICK, triadPlanet);
v[3].addEventListener(MouseEvent.CLICK, analogPlanet);
v[4].addEventListener(MouseEvent.CLICK, monoPlanet);
v[5].addEventListener(MouseEvent.CLICK, complementPlanet);
for (var i:uint; i < v.length; i++) {
addChild(v[i]);
}
addText();
randomPlanet(null);
}
private function addText():void {
_txt = new TextField();
var s:Sprite = new Sprite();
_txt.defaultTextFormat = new TextFormat("Verdana", 12, 0xaaaaaa, false, null, null, null, null, "center");
_txt.text = "Planet Harmony Research";
addChild(_txt);
_txt.y = 20;
_txt.width = 450;
_txt.height = 50;
}
private function button(x:int = 0, y:int = 0, name:String = "Yoo", w:int = 50, h:int = 30):SimpleButton {
var im1:BitmapData = new BitmapData(w, h, false, 0x000000);
var im2:BitmapData = new BitmapData(w, h, false, 0x000000);
var im3:BitmapData = new BitmapData(w, h, false, 0x000000);
var txt:TextField = new TextField();
var s:Sprite = new Sprite();
txt.defaultTextFormat = new TextFormat("Verdana", 10, 0xaaaaaa, false, null, null, null, null, "center");
txt.text = name;
txt.width = w;
txt.height = 20;
txt.y = (h >> 1) - 10;
s.addChild(txt);
s.graphics.lineStyle(2, 0x757575);
s.graphics.beginFill(0x808080);
s.graphics.drawRect(0, 0, w, h);
s.graphics.endFill();
im1.draw(s);
s.graphics.clear();
s.graphics.beginFill(0x707070);
s.graphics.drawRect(0, 0, w, h);
s.graphics.endFill();
im2.draw(s);
s.graphics.clear();
s.graphics.beginFill(0xaa7070);
s.graphics.drawRect(0, 0, w, h);
s.graphics.endFill();
im3.draw(s);
var bitm1:Bitmap = new Bitmap(im1);
var bitm2:Bitmap = new Bitmap(im2);
var bitm3:Bitmap = new Bitmap(im3);
var b:SimpleButton = new SimpleButton(bitm1, bitm2, bitm3, bitm1);
b.x = x;
b.y = y;
return b;
}
private function randomPlanet(e:MouseEvent = null):void {
planetColor( int(Math.random() * 4) );
}
private function triadPlanet(e:MouseEvent = null):void {
planetColor( 0 );
}
private function complementPlanet(e:MouseEvent = null):void {
planetColor( 1 );
}
private function analogPlanet(e:MouseEvent = null):void {
planetColor( 2 );
}
private function monoPlanet(e:MouseEvent = null):void {
planetColor( 3 );
}
private function planetColor(n:int):void {
_groundColors = new Vector.<uint>(3, true);
_skyColors = new Vector.<uint>(6, true);
var name:String;
var sat:Number = randomNumber(0.4, 0.8);
var dist:Number = randomNumber(0.6, 1);
var ang1:int = randomNumber(0, 360);
var baseColor:uint = hsvToHex(ang1, sat, dist);
var a2:int, a3:int, ang2:int, ang3:int;
var n2:int = int(Math.random() * 2);
switch (n) {
case 0:
name = "Triad Planet Harmony";
if (ang1 < 120) {
a2 = ang1 + 120;
a3 = ang1 + 240
} else if (ang1 > 120 && ang1 < 240) {
a2 = ang1 + 120;
a3 = ang1 - 120
} else {
a2 = ang1 - 120;
a3 = ang1 - 240
}
// switch dominant 2
if (n2 == 0) {
ang2 = a2;
ang3 = a3;
} else {
ang3 = a2;
ang2 = a3;
}
_groundColors[0] = hsvToHex(ang2, sat, dist);
_groundColors[1] = hsvToHex(ang3, sat, dist);
_groundColors[2] = hsvToHex(ang3, sat, dist/2);
_skyColors[0] = hsvToHex(ang2, sat, dist); // fog
_skyColors[1] = hsvToHex(ang1, sat, dist); // sky
_skyColors[2] = hsvToHex(ang1, sat, dist/2); // top sky
_skyColors[3] = hsvToHex(ang1, 0.1, 1); // clound white
_skyColors[4] = hsvToHex(ang1, sat, 0.1); // clound black
_skyColors[5] = hsvToHex(ang1, 0.1, 1); // sun
break;
case 1:
name = "Complementary Planet Harmony";
if (ang1 < 180) ang2 = ang1 + 180;
else ang2 = ang1 - 180;
_groundColors[0] = hsvToHex(ang2, sat, dist);
_groundColors[1] = hsvToHex(ang2, sat, (dist/3)*2);
_groundColors[2] = hsvToHex(ang2, sat, (dist/3));
_skyColors[0] = hsvToHex(ang2, sat, dist); // fog
_skyColors[1] = hsvToHex(ang1, sat, dist); // sky
_skyColors[2] = hsvToHex(ang1, sat, dist/2); // top sky
_skyColors[3] = hsvToHex(ang1, 0.1, 1); // clound white
_skyColors[4] = hsvToHex(ang1, sat, 0.1); // clound black
_skyColors[5] = hsvToHex(ang1, 0.1, 1); // sun
break;
case 2:
name = "Analogous Planet Harmony";
if (ang1 < 300){ ang2 = ang1 + 30; ang3 = ang1 + 60; }
else { ang2 = ang1 - 30; ang3 = ang1 - 60; }
_groundColors[0] = hsvToHex(ang2, sat, dist);
_groundColors[1] = hsvToHex(ang3, sat, dist);
_groundColors[2] = hsvToHex(ang3, sat, dist / 2);
_skyColors[0] = _groundColors[0]// fog
_skyColors[1] = hsvToHex(ang1, sat, dist); // sky
_skyColors[2] = hsvToHex(ang1, sat, dist/2); // top sky
_skyColors[3] = hsvToHex(ang1, 0.1, 1); // clound white
_skyColors[4] = hsvToHex(ang1, sat, 0.1); // clound black
_skyColors[5] = hsvToHex(ang1, 0.1, 1); // sun
break;
case 3:
name = "Monochrome Planet Harmony";
_groundColors[0] = hsvToHex(ang1, sat, dist);
_groundColors[1] = hsvToHex(ang1, sat, (dist/3)*2);
_groundColors[2] = hsvToHex(ang1, sat, (dist/3));
_skyColors[0] = _groundColors[0] // fog
_skyColors[1] = hsvToHex(ang1, sat/2, dist); // sky
_skyColors[2] = hsvToHex(ang1, sat/2, dist/2); // top sky
_skyColors[3] = hsvToHex(ang1, 0.1, 1); // clound white
_skyColors[4] = hsvToHex(ang1, sat/2, 0.1); // clound black
_skyColors[5] = hsvToHex(ang1, 0.1, 1); // sun
break;
}
if (_txt)
_txt.text = name;
drawPlanet(_groundColors, _skyColors);
}
private function drawPlanet(gc:Vector.<uint>, gs:Vector.<uint>):void {
_canvas.lock();
var m:Matrix = new Matrix();
m.createGradientBox(360, 360, -Math.PI / 2);
var s:Sprite = new Sprite();
s.graphics.beginGradientFill("linear", [gc[0], gs[1] , gs[1], gs[2]], [1, 1, 1, 1], [0x22,0x66, 0xAA, 0xff], m);
s.graphics.drawRect(0, 0, 360, 360);
s.graphics.endFill();
var min:int = 180
var max:int = 300;
var middle:int = 222;
m = new Matrix();
m.createGradientBox(360, 138, -Math.PI / 2, 0, 222);
var py:int = 0
var mont:Vector.<int> = new Vector.<int>();
mont[0] = randomNumber(min, max);
mont[1] = randomNumber(min, max);
mont[2] = randomNumber(min, max);
mont[3] = randomNumber(min, max);
mont[4] = randomNumber(min, max);
mont[5] = randomNumber(min, max);
mont[6] = randomNumber(min, max);
mont[7] = randomNumber(min, max);
mont[8] = randomNumber(min, max);
mont[9] = randomNumber(min, max);
mont[10] = randomNumber(min, max);
mont[11] = randomNumber(min, max);
var g:Sprite = new Sprite();
g.graphics.beginFill(gc[0]);
g.graphics.moveTo(380, 380);
g.graphics.lineTo(-30, 380);
g.graphics.lineTo(-30, 222);
g.graphics.curveTo(30, mont[0], 60, mont[6]);
g.graphics.curveTo(90, mont[1], 120, mont[7]);
g.graphics.curveTo(140, mont[2], 180, mont[8]);
g.graphics.curveTo(210, mont[3], 240, mont[9]);
g.graphics.curveTo(270, mont[4], 300, mont[10]);
g.graphics.curveTo(330, mont[5], 380, mont[11]);
g.graphics.lineTo(380, 200);
g.filters = [new BevelFilter(10, 45, gs[5], 1, gs[1], 1, 30, 30, 1, 2), new BlurFilter(6, 6, 3)]
py = 50;
var h:Sprite = new Sprite();
h.graphics.beginFill(gc[1]);
h.graphics.moveTo(380, 380);
h.graphics.lineTo(-30, 380);
h.graphics.lineTo(-30, 280);
h.graphics.curveTo(30, mont[0] + py, 60, mont[6] + py);
h.graphics.curveTo(90, mont[1] + py, 120, mont[7] + py);
h.graphics.curveTo(140, mont[2] + py, 180, mont[8] + py);
h.graphics.curveTo(210, mont[3] + py, 240, mont[9] + py);
h.graphics.curveTo(270, mont[4] + py, 300, mont[10] + py);
h.graphics.curveTo(330, mont[5] + py, 380, mont[11] + py);
h.graphics.lineTo(380, 200);
h.filters = [new BevelFilter(10, 45 + 180, gc[0], 1, gc[0], 1, 30, 30, 1, 2), new BlurFilter(12, 12, 3)]
py = 100;
var h2:Sprite = new Sprite();
h2.graphics.beginFill(gc[2]);
h2.graphics.moveTo(380, 380);
h2.graphics.lineTo(-30, 380);
h2.graphics.lineTo(-30, 280);
h2.graphics.curveTo(30, mont[0] + py, 60, mont[6] + py);
h2.graphics.curveTo(90, mont[1] + py, 120, mont[7] + py);
h2.graphics.curveTo(140, mont[2] + py, 180, mont[8] + py);
h2.graphics.curveTo(210, mont[3] + py, 240, mont[9] + py);
h2.graphics.curveTo(270, mont[4] + py, 300, mont[10] + py);
h2.graphics.curveTo(330, mont[5] + py, 380, mont[11] + py);
h2.graphics.lineTo(380, 200);
h2.filters = [new BevelFilter(10, 45 + 180, gc[1], 1, gc[1], 1, 30, 30, 1, 2), new BlurFilter(8, 8, 3)]
_canvas.draw(s);
_canvas.draw(sunColor( gs[5]));
_canvas.draw(createCloud(360, 360 / GOLD, Math.random() * 0xffffffff, 1, gs[3], gs[1], gs[4]));
_canvas.draw(g);
_canvas.draw(h);
_canvas.draw(h2);
_canvas.unlock();
}
private function drawLinear(e:MouseEvent):void {
palette("linear");
}
private function drawRadial(e:MouseEvent):void {
palette("radial");
}
private function palette(type:String = "linear"):void {
_canvas.lock();
var size:int = _canvas.width * _canvas.height;
var xp:int, yp:int, c:uint, i:int;
if (type == "linear") {
for (i = 0; i < size; i++) {
xp = i % 360;
yp = i / 360;
c = hsvToHex(xp, 1, yp / 360);
_canvas.setPixel(xp, yp, c);
}
} else {
// radial
var dx:Number, dy:Number, dist:Number, ang:Number;
for (i = 0; i < size; i++) {
xp = i % 360;
yp = i / 360;
dx = xp - 180;
dy = yp - 180;
dist = 1 - Math.sqrt((dx * dx) + (dy * dy)) / 360;
ang = Math.atan2(dy, dx) / Math.PI * 180;
if (ang < 0) {
ang += 360;
}
c = hsvToHex(ang, 1, dist);
_canvas.setPixel(xp, yp, c);
}
}
_canvas.unlock();
}
private function hsvToHex(h:Number, s:Number, v:Number):uint {
var n:Vector3D = new Vector3D();
var i:int, f:Number, p:Number, q:Number, t:Number, c:Array;
if (h > 360)
h = 360 - h;
if (s == 0) {
n.x = n.y = n.z = v;
c = [Math.round(n.x * 255), Math.round(n.y * 255), Math.round(n.z * 255)];
return c[0] << 16 | c[1] << 8 | c[2];
}
h /= 60;
i = Math.floor(h);
f = h - i;
p = v * (1 - s);
q = v * (1 - s * f);
t = v * (1 - s * (1 - f));
switch (i) {
case 0:
n = new Vector3D(v, t, p);
break;
case 1:
n = new Vector3D(q, v, p);
break;
case 2:
n = new Vector3D(p, v, t);
break;
case 3:
n = new Vector3D(p, q, v);
break;
case 4:
n = new Vector3D(t, p, v);
break;
default:
n = new Vector3D(v, p, q);
break;
}
c = [Math.round(n.x * 255), Math.round(n.y * 255), Math.round(n.z * 255)];
return c[0] << 16 | c[1] << 8 | c[2];
}
public function randomNumber(min:Number, max:Number):Number {
return (min + Math.random() * (max - min));
}
private function sunColor(c:uint):BitmapData {
var b:BitmapData = new BitmapData(128, 128, true, 0x00000000);
var s:Sprite = new Sprite();
var mtx:Matrix = new Matrix();
mtx.createGradientBox(128, 128, 0, 0, 0);
s.graphics.beginGradientFill("radial", [c, c, c, c, c], [1, .95, .4, .1, 0], [0, 20, 50, 150, 255], mtx);
s.graphics.drawCircle(64, 64, 64);
s.graphics.endFill();
b.draw(s);
return b;
}
public function createCloud(width:int, height:int, seed:int, contrast:Number = 1, color:uint = 0x0080FF, light:uint = 0xFFFFFF, shadow:uint = 0xDDDDDD):BitmapData {
var gradiation:Sprite = new Sprite();
var drawMatrix:Matrix = new Matrix();
drawMatrix.createGradientBox(width, height);
gradiation.graphics.beginGradientFill("radial", [0x000000, 0x000000], [0, 1], [0, 255], drawMatrix);
gradiation.graphics.drawRect(0, 0, width, height);
gradiation.graphics.endFill();
var alphaBmp:BitmapData = new BitmapData(width, height);
alphaBmp.perlinNoise(width / 3, height / 2.5, 5, seed, false, true, 1 | 2 | 4, true);
var zoom:Number = 1 + (contrast - 0.1) / (contrast + 0.9);
if (contrast < 0.1)
zoom = 1;
if (contrast > 2.0)
zoom = 2;
var ctMatrix:Array = [contrast + 1, 0, 0, 0, -128 * contrast, 0, contrast + 1, 0, 0, -128 * contrast, 0, 0, contrast + 1, 0, -128 * contrast, 0, 0, 0, 1, 0];
alphaBmp.draw(gradiation, new Matrix(zoom, 0, 0, zoom, -(zoom - 1) / 2 * width, -(zoom - 1) / 2 * height));
alphaBmp.applyFilter(alphaBmp, alphaBmp.rect, new Point(), new ColorMatrixFilter(ctMatrix));
var image:BitmapData = new BitmapData(width, height, true, 0xFF << 24 | color);
image.copyChannel(alphaBmp, alphaBmp.rect, new Point(), 4, 8);
image.applyFilter(image, image.rect, new Point(), new GlowFilter(light, 1, 4, 4, 1, 3, true));
var bevelSize:Number = Math.min(width, height) / 30;
image.applyFilter(image, image.rect, new Point(), new BevelFilter(bevelSize, 45, light, 1, shadow, 1, bevelSize / 5, bevelSize / 5, 1, 3));
var image2:BitmapData = new BitmapData(width, height, true, 0);
image2.draw(createGradientRect(width, height, [light, color, shadow], [1, 0.2, 1], null, 90), null, null, BlendMode.MULTIPLY);
image2.copyChannel(alphaBmp, alphaBmp.rect, new Point(), 4, 8);
image.draw(image2, null, null, BlendMode.MULTIPLY);
alphaBmp.dispose();
return image;
}
public function createGradientRect(width:Number, height:Number, colors:Array, alphas:Array, ratios:Array = null, rotation:Number = 0):Sprite {
var i:int, rts:Array = new Array();
if (ratios == null)
for (i = 0; i < colors.length; i++)
rts.push(int(255 * i / (colors.length - 1)));
else
for (i = 0; i < ratios.length; i++)
rts[i] = Math.round(ratios[i] * 255);
var sp:Sprite = new Sprite();
var mtx:Matrix = new Matrix();
mtx.createGradientBox(width, height, Math.PI / 180 * rotation, 0, 0);
if (colors.length == 1 && alphas.length == 1)
sp.graphics.beginFill(colors[0], alphas[0]);
else
sp.graphics.beginGradientFill("linear", colors, alphas, rts, mtx);
sp.graphics.drawRect(0, 0, width, height);
sp.graphics.endFill();
return sp;
}
}
}