YIQ Color Cube
/**
* Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/A25N
*/
package {
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.Event;
import net.hires.debug.Stats;
[SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#000000")]
/**
* YIQ Color Cube
* @see http://wonderfl.net/c/3AnJ
* @author Aquioux
*/
public class Main extends Sprite {
private var viewer_:Bitmap; // ビューア
private var draw_:BitmapDataDraw; // ビューアが表示する BitmapData を生成
private var calc_:Calculate; // BitmapDataDraw に表示する内容を計算
/**
* コンストラクタ
*/
public function Main() {
setup();
addEventListener(Event.ENTER_FRAME, update);
}
// 初期化
private function setup():void {
var sw:int = stage.stageWidth;
var sh:int = stage.stageHeight;
calc_ = new Calculate();
calc_.setup(sw, sh);
draw_ = new BitmapDataDraw();
draw_.setup(sw, sh);
viewer_ = new Bitmap();
addChild(viewer_);
}
// ループ
private function update(e:Event):void {
calc_.update(mouseX, mouseY);
draw_.update(calc_.data);
viewer_.bitmapData = draw_.bitmapData;
}
}
}
//package {
// import aquioux.geom.Number4;
import flash.geom.Matrix3D;
import flash.geom.PerspectiveProjection;
import flash.geom.Point;
import flash.geom.Utils3D;
import flash.geom.Vector3D;
/**
* BitmapDataDraw に表示する内容を計算
* @author Aquioux
*/
/*public*/ class Calculate {
/**
* Viewer に渡す座標データ
*/
public function get data():Vector.<Number> { return _data; }
private var _data:Vector.<Number>;
// 各座標軸のオフセット
private var offsetX_:Number = 0.0;
private var offsetY_:Number = 0.0;
private var offsetZ_:Number = 75.0;
// Utils3D.projectVectors 用
private var m_:Matrix3D;
private var verts_:Vector.<Number>;
private var projectedVerts_:Vector.<Number>;
private var uvts_:Vector.<Number>;
// PerspectiveProjection
private var projection_:PerspectiveProjection;
private var projectionMatrix3D_:Matrix3D;
// 座標移動用
private var vx_:Number = 0.0;
private var vy_:Number = 0.0;
private var speed_:Number = 0.015;
private var colors_:Vector.<uint>;
/**
* コンストラクタ
*/
public function Calculate() {
}
/**
* 初期化
* @param w ステージ幅
* @param h ステージ高
*/
public function setup(w:Number, h:Number):void {
offsetX_ = w / 2;
offsetY_ = h / 2;
var factory:DataFactory = new DataFactory();
// Utils3D.projectVectors 用
m_ = new Matrix3D();
verts_ = factory.verts;
var n:uint = factory.verts.length / 3;
projectedVerts_ = new Vector.<Number>(n * 2, true);
uvts_ = new Vector.<Number>(n * 3, true);
colors_ = factory.colors;
_data = new Vector.<Number>(n * 3, true);
// PerspectiveProjection
projection_ = new PerspectiveProjection();
projectionMatrix3D_ = projection_.toMatrix3D();
}
/**
* ループ
*/
public function update(mouseX:Number, mouseY:Number):void {
vx_ += (offsetX_ - mouseX) * speed_;
vy_ -= (offsetY_ - mouseY) * speed_;
m_.identity();
m_.appendRotation(vy_, Vector3D.X_AXIS);
m_.appendRotation(vx_, Vector3D.Y_AXIS);
m_.appendTranslation(0, 0, offsetZ_);
m_.append(projectionMatrix3D_);
Utils3D.projectVectors(m_, verts_, projectedVerts_, uvts_);
// 回転を適用した外部データを zsort
var sort:Array = [];
var n:uint = projectedVerts_.length / 2;
for (var i:int = 0; i < n; i++) {
var v:Number4 = new Number4();
v.x = projectedVerts_[i * 2] + offsetX_;
v.y = projectedVerts_[i * 2 + 1] + offsetY_;
v.z = uvts_[i * 3 + 2];
v.w = colors_[i];
sort.push(v);
}
sort.sortOn("z", Array.NUMERIC);
// sort した Array から必要なデータを生成し、Vector.<Number> に代入
var zLevel:Number = 1 / offsetZ_;
for (i = 0; i < n; i++) {
v = sort[i];
_data[i * 3] = v.x;
_data[i * 3 + 1] = v.y;
_data[i * 3 + 2] = v.w;
}
}
}
//}
//package aquioux.geom {
/**
* Number 型変数を4つまとめて扱うクラス
* 用途:ARGB形式の色、三次元座標+もうひとつの要素
* @author YOSHIDA, Akio (Aquioux)
*/
/*public*/ class Number4 {
/**
* 1つめの Number 型変数
* ARGBカラーのおける赤
*/
// ARGB の赤
public function get r():Number { return _a; }
public function set r(value:Number):void { _a = value; }
// 三次元座標のX座標
public function get x():Number { return _a; }
public function set x(value:Number):void { _a = value; }
private var _a:Number;
/**
* 2つめの Number 型変数
* ARGBカラーのおける緑
*/
// ARGB の緑
public function get g():Number { return _b; }
public function set g(value:Number):void { _b = value; }
// 三次元座標のY座標
public function get y():Number { return _b; }
public function set y(value:Number):void { _b = value; }
private var _b:Number;
/**
* 3つめの Number 型変数
* ARGBカラーのおける青
*/
// ARGB の青
public function get b():Number { return _c; }
public function set b(value:Number):void { _c = value; }
// 三次元座標のZ座標
public function get z():Number { return _c; }
public function set z(value:Number):void { _c = value; }
private var _c:Number;
/**
* 4つめの Number 型変数
* ARGBカラーのおけるアルファ値
*/
// ARGB のアルファ値
public function get a():Number { return _d; }
public function set a(value:Number):void { _d = value; }
// 三次元座標と同時に管理するもうひとつの要素
public function get w():Number { return _d; }
public function set w(value:Number):void { _d = value; }
private var _d:Number;
/**
* コンストラクタ
* @param a 1つめの変数
* @param b 2つめの変数
* @param c 3つめの変数
* @param d 4つめの変数
*/
public function Number4(a:Number = 0.0, b:Number = 0.0, c:Number = 0.0, d:Number = 0.0) {
_a = a;
_b = b;
_c = c;
_d = d;
}
/**
* 複製
* @return 複製した Number4 インスタンス
*/
public function clone():Number4 {
return new Number4(_a, _b, _c, _d);
}
/**
* 表示
* @return 表示内容
*/
public function toString():String {
return "Number4(" + _a + ", " + _b + ", " + _c + ", " + _d + ")";
}
}
//}
//package {
/*public*/ class DataFactory {
// 外部に渡すデータ(三次元座標)
public function get verts():Vector.<Number> { return _verts; }
private var _verts:Vector.<Number> = new Vector.<Number>();
public function get colors():Vector.<uint> { return _colors; }
private var _colors:Vector.<uint> = new Vector.<uint>();
public function DataFactory() {
var numX:int = 14;
var numY:int = 14;
var numZ:int = 14;
var intervalPosition:int = 2;
var offsetX:Number = (numX - 1) * intervalPosition / 2;
var offsetY:Number = (numY - 1) * intervalPosition / 2;
var offsetZ:Number = (numZ - 1) * intervalPosition / 2;
var intervalY:Number = 1 / (numZ - 1);
var intervalI:Number = 2 / (numX - 1);
var intervalQ:Number = 2 / (numY - 1);
var offsetI:int = 1;
var offsetQ:int = 1;
for (var cz:int = 0; cz < numZ; cz++) {
var pz:Number = cz * intervalPosition - offsetZ;
var y:Number = intervalY * cz;
for (var cy:int = 0; cy < numY; cy++) {
var py:Number = cy * intervalPosition - offsetY;
var q:Number = intervalQ * cy - offsetQ;
for (var cx:int = 0; cx < numX; cx++) {
var px:Number = cx * intervalPosition - offsetX;
_verts.push(px, py, pz);
var i:Number = intervalI * cx - offsetI;
_colors.push(yiqToRgb(y, i, q));
}
}
}
_verts.fixed = true;
_colors.fixed = true;
}
private function yiqToRgb(y:Number, i:Number, q:Number):uint {
// http://en.wikipedia.org/wiki/YIQ
var r:Number = y + 0.9563 * i + 0.6210 * q;
var g:Number = y - 0.2721 * i - 0.6474 * q;
var b:Number = y - 1.1070 * i + 1.7046 * q;
r *= 255;
g *= 255;
b *= 255;
r >> 0;
g >> 0;
b >> 0;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
if (r > 255) r = 255;
if (g > 255) g = 255;
if (b > 255) b = 255;
return r << 16 | g << 8 | b;
}
}
//}
//package {
import flash.display.BitmapData;
/**
* ビューアが表示する BitmapData を生成
* @author YOSHIDA, Akio (Aquioux)
*/
/*public*/ class BitmapDataDraw {
/**
* View に渡す BitmapData
*/
public function get bitmapData():BitmapData { return _bitmapData; }
private var _bitmapData:BitmapData;
/**
* コンストラクタ
*/
public function BitmapDataDraw() {
}
/**
* 初期化
* @param w ステージ幅
* @param h ステージ高
*/
public function setup(w:Number, h:Number):void {
_bitmapData = new BitmapData(w, h, false, 0x000000);
}
/**
* ループ
* @param data 描画のための座標データ(1次元 Vector)
*/
public function update(data:Vector.<Number>):void {
_bitmapData.lock();
_bitmapData.fillRect(_bitmapData.rect, 0x000000);
var len:int = data.length;
for (var i:int = 0; i < len; i += 3) {
_bitmapData.setPixel(data[i], data[i + 1], data[i + 2]);
}
_bitmapData.unlock();
}
}
//}