bitmap 3d sphere
...
@author lizhi
/**
* Copyright lizhi ( http://wonderfl.net/user/lizhi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/7vxO
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Vector3D;
import flash.net.FileReference;
import sliz.miniui.Button;
/**
* ...
* @author lizhi
*/
public class TestBitmapSphere extends Sprite
{
private var sphere:BitmapSphere;
private var cx:int;
private var cy:int;
private var light:Sprite = new Sprite;
private var file:FileReference;
private var loader:Loader;
public function TestBitmapSphere()
{
var target:BitmapData = new BitmapData(200, 200, false, 0xffffff);
var image:Bitmap = new Bitmap(target);
addChild(image);
image.x = stage.stageWidth / 2 - image.width / 2;
image.y = stage.stageHeight / 2 - image.height / 2;
cx = image.x + image.width / 2;
cy = image.y + image.height / 2;
var source:BitmapData = new BitmapData(100, 100, false, 0);
for (var y:int = 0; y < source.height; y++ ) {
for (var x:int = 0; x < source.width; x++ ) {
var f1:Boolean = x % 10 >= 5;
var f2:Boolean = y % 10 >= 5;
source.setPixel(x, y, (((f1&&f2)||(!f1&&!f2))?0x808000:0xffffff));
}
}
light.graphics.beginFill(0xFFFF00);
light.graphics.drawCircle(0, 0, 20);
addChild(light);
light.addEventListener(MouseEvent.MOUSE_DOWN, onmd);
stage.addEventListener(MouseEvent.MOUSE_UP, onmu);
light.x = 200;
light.y = 200;
sphere = new BitmapSphere(target, source, new Vector3D(light.x, light.y, 150));
addEventListener(Event.ENTER_FRAME, update);
//addChild(sphere.pen);
var explorer:Button = new Button("explorer", 2, 20, this, browse);
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoad2);
}
private function browse(e:Event):void {
file = new FileReference();
file.browse();
file.addEventListener(Event.SELECT, onSelect);
}
private function onSelect(e:Event):void {
file.load();
file.addEventListener(Event.COMPLETE, onLoad);
}
private function onLoad(e:Event):void {
loader.loadBytes(file.data);
}
private function onLoad2(e:Event):void {
var content:Bitmap = loader.contentLoaderInfo.content as Bitmap;
sphere.source = content.bitmapData;
}
private function onmu(e:MouseEvent):void
{
light.stopDrag();
}
private function onmd(e:MouseEvent):void
{
light.startDrag();
}
private function update(e:Event):void
{
sphere.light.x = light.x;
sphere.light.y = light.y;
sphere.ry+=(mouseX-cx)/50;
sphere.rx+=(mouseY-cy)/50;
sphere.rz += 0.01;
sphere.render();
}
}
}
import flash.display.BitmapData;
import flash.display.Shape;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Vector3D;
/**
* ...
* @author lizhi
*/
class BitmapSphere
{
private var _target:BitmapData;
private var _source:BitmapData;
private var csource:BitmapData;
private var m:Matrix = new Matrix;
public var pen:Shape = new Shape;
private var _light:Vector3D;
private var _rx:Number = 0;
private var _ry:Number = 0;
private var _rz:Number = 0;
private var map:Array = [];
private var w:int;
private var h:int;
private var r:Number;
private var sw:int;
private var sh:int;
private var hsw:int;
private var hsh:int;
public function BitmapSphere(target:BitmapData,source:BitmapData,light:Vector3D)
{
_target = target;
_source = source;
_light = light;
init();
}
private function init():void {
csource = source.clone();
w = _target.width;
h = _target.height;
r = w / 2;
sw = _source.width;
sh = _source.height;
hsw = sw / 2;
hsh = sh / 2;
map = [];
for (var y:int = 0; y < h; y++ ) {
var r1:Number = Math.sqrt(r * r - (r - y) * (r - y));
for (var x:int = 0; x < w; x++ ) {
if (map[x] == null) map[x] = [];
var v:V = new V;
v.p = getSpherizePoint(new Point(x, y), r, r, new Point(r, r));
var z:Number = -Math.sqrt(r1 * r1 - (r - x) * (r - x));
v.z = z;
var n:Vector3D = new Vector3D(x - r, y - r, z);
n.normalize();
v.n = n;
map[x][y] = v;
}
}
}
public function render():void {
m.identity();
m.translate(ry, rx);
m.translate( -hsw, -hsh);
m.rotate(rz);
m.translate(hsw, hsh);
pen.graphics.clear();
pen.graphics.beginBitmapFill(_source, m);
pen.graphics.drawRect(0, 0, sw, sh);
csource.fillRect(csource.rect, 0xffffff);
csource.draw(pen);
_target.lock();
for (var y:int = 0; y < h; y++ ) {
for (var x:int = 0; x < w;x++ ) {
var v:V = map[x][y];
if (isNaN(v.z)) continue;
var c:Number = csource.getPixel(v.p.x, v.p.y);
var a:Number = Vector3D.angleBetween(v.n, light) / Math.PI;
_target.setPixel(x, y, (((c << 8 >>> 24) * a) << 16) | (((c << 16 >>> 24) * a) << 8) | ((c << 24 >>> 24) * a));
}
}
_target.unlock();
}
public function getSpherizePoint(point:Point, r:Number, h:Number, cp:Point):Point {
var R:Number = (r * r + h * h) / (2 * h);
var l:Number = Point.distance(point, cp);
var p:Point = Point.interpolate(Point.interpolate(point, cp, r / l), cp, Math.asin(l / R) / Math.acos((R - h) / R));
p.normalize(p.length*(Math.min(sw,sh))/w);
return p;
}
public function get rx():Number { return _rx; }
public function set rx(value:Number):void
{
_rx = value;
}
public function get target():BitmapData { return _target; }
public function set target(value:BitmapData):void
{
_target = value;
}
public function get source():BitmapData { return _source; }
public function set source(value:BitmapData):void
{
_source = value;
init();
}
public function get ry():Number { return _ry; }
public function set ry(value:Number):void
{
_ry = value;
}
public function get rz():Number { return _rz; }
public function set rz(value:Number):void
{
_rz = value;
}
public function get light():Vector3D { return _light; }
public function set light(value:Vector3D):void
{
_light = value;
}
}
class V {
public var p:flash.geom.Point;
public var z:Number;
public var n:flash.geom.Vector3D;
}